C - 超出类型字符串的范围

问题描述 投票:2回答:3

我试图解决CS50的一些问题集。我需要提取字符串“stra”的前两个字符,然后连接它们并转换为字符串,然后将该字符串与数组中的字符串进行比较。我已经读到很多,在C中没有字符串,只有字符数组,但在CS50中它们使用字符串声明类型。当我运行代码时,它给了我下面的错误

运行时错误:索引4超出类型'string [4]'的范围

#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void){

   string stra = "GH7";

   int x = 0;
   //extract first two chars of stra
   char strb[3] = {stra[0], stra[1], '\0'};
   //concatenate chars
   string strc = strb;

   string letters[] = {"AB","CD","ED","GH"};

   for (int i = 0, n = sizeof(letters); i < n; i++)
   {
      if (strc == letters[i])  // <--the error happens here
      {
         break;
      }
      else
      {
         x++;
      }
   }
   printf("%i", x);
}

它给了我这个错误

运行时错误:索引4超出类型'string [4]'的范围

c cs50
3个回答
5
投票

问题是初始化

n = sizeof(letters)

sizeof(letters)应该除以单个元素(指针)的大小:

n = sizeof(letters) / sizeof(*letters)

(除非你确定letters指向一个字符串文字,这是多余的,这是计算litteral数组大小的最佳方法,它甚至可以跟随一个可能的类型更改)


0
投票

你想迭代元素'字符串'数组letters。要计算数字元素,最好的方法是获取数组的大小并将其除以第一个元素的大小。

见下面的例子:

//#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void){

    char *stra = "GH7";

    int x = 0;
    //extract first two chars of stra

    char strb[3] = {stra[0], stra[1], '\0'};

    //concatenate chars
    char *strc = strb;

    printf("strc: %s\n", strc);

    char * letters[] = {"AB","CD","ED","GH"};

    // number of element in the `letters` 

    int nr_of_elements = sizeof(letters)/sizeof(letters[0]);

    printf("sizeof letters= %d,  sizeof the element= %d   nr_of_elements= %d \n", sizeof(letters), sizeof(letters[0]), nr_of_elements);

    for (int i = 0, n = nr_of_elements;  i < n;  i++)
    {
      if (strc == letters[i])  // <--the error happens here
      {
         break;
      }
     else
      {
         x++;
      }
    }

    printf("x= %i", x);
    return 0;
}

输出:

strc: GH
sizeof letters= 32,  sizeof the element= 8   nr_of_elements= 4 
x= 4

0
投票

<无偿的咆哮>

string是谎言。它是char *类型的typedef(别名),它不是字符串。字符串是一个字符序列,后跟一个0值终止符。字符串存储在char(或wchar_t用于“宽”字符串)的数组中。 char *可能指向字符串中的第一个字符,或者它可能指向序列中不是字符串的第一个字符,或者它可能指向不属于任何序列的单个字符。绝对不是一个字符串。 string类型的对象包含地址,而不是实际的字符串。

它在CS50.h头文件中的存在是一个混乱的源头,也是你学习正确的C字符串语义的主动障碍。如果您有选择,请不要使用它。

</ gratuitous rant>

正如让 - 弗朗索瓦指出的那样,sizeof返回一个对象的总字节数;如果要获取数组中元素的数量,则必须将数组的总大小除以单个元素的大小:

T arr[] = { /* some values of type T */ }; // for any type T
size_t count = sizeof arr / sizeof arr[0]; // or divide by sizeof *arr

请记住,sizeof是一个运算符,而不是一个函数 - 如果操作数不是类型名称,则不需要用括号括起来(尽管它们不会受到伤害)。

请注意,这仅适用于数组表达式,而不适用于指针。请记住,在大多数情况下,数组类型的表达式将被转换(“衰减”)为指针类型的表达式,表达式的值将是第一个element1的地址。如果您尝试编写一个将数组作为参数并返回计数的函数,则类似于

size_t elt_count( int arr[] )
{
  return sizeof arr / sizeof arr[0];
}

你不会得到你所期望的,因为在这种情况下,arr是一个指针,而不是一个数组2。


  1. 除非它是sizeof或一元&运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则将将“T的N元素数组”类型的表达式转换为(“decay”) “指向T的指针”类型的表达式和表达式的值将是数组的第一个元素的地址。
  2. 在函数参数声明的上下文中,T a[N]T a[]被解释为T *a;这三个人都宣称a是指向T的指针。

© www.soinside.com 2019 - 2024. All rights reserved.