【问题标题】:Print one character from string从字符串中打印一个字符
【发布时间】:2017-11-23 13:24:49
【问题描述】:

我遇到了一个与从 c 中的字符串打印一个字符有关的问题。 该函数从用户那里获取两个变量 - 数字(应该从字符串中打印字符的数字)和字符串。当我输入字符串“Martin”并且数字为 5 时,输出为“i”。但是当数字大于字符串长度时,就会出现问题,我实际上不知道出了什么问题。

附言。如果数字长于字符串大小,则应打印“Nothing”。

void printLetter() {

    char * string = (char*)malloc(sizeof(char));
    int n;

    printf("Number:\n");
    scanf("%i", &n);
    printf("String:\n");
    scanf("%s", string);

    if(n > strlen(string)) {
        printf("nothing");
    } else {
        printf("%c\n", string[n+1]);
    }

    free(string);


} 

【问题讨论】:

  • char * string = malloc(sizeof(char)); 您正在为单个 char 分配空间 - 因此,如果您尝试编写更多内容(在 scanf("%s", string); 中),您已经得到 未定义的行为
  • 所以我应该这样分配它:char * string = malloc(100* sizeof(char));?
  • @UnholySheep scanf("%0s", string);scanf("%*s", string); 如果首先调用 string[0]='\0'; 会很安全 :)
  • 是的,您需要分配更多 - 100 应该足够了。另请注意,在此特定代码中,您实际上不需要使用mallocfree,您可以只声明一个char 数组(例如:char string[100];
  • string[n+1]-->string[n-1]...您也只为字符串变量分配了 1 个字节。

标签: c arrays string memory-management io


【解决方案1】:

这里不需要动态分配,因为你事先不知道字符串的长度,所以就这样做:

void printLetter() {
    char string[100]; // example size 100
    ...
    scanf("%99s", string); // read no more than your array can hold
}

一个有趣的练习是计算字符串的长度,根据需要动态分配完全一致的空间(+1 为空终止符),将string 复制到动态分配的空间,根据需要使用它,然后释放它。


此外:

printf("%c\n", string[n+1]);

应该这样写:

printf("%c\n", string[n-1]);

因为您不想超出数组的边界(并导致未定义的行为),或者在请求的字符旁边打印两个字符,因为当我要求第一个字符时,您应该打印string[0],当我要求第二个时,您应该打印string[1],依此类推。所以你明白为什么我们需要打印string[n-1],当用户要求n-th 字母时。

顺便说一句,在处理i索引时,通常使用名为i 的变量,而不是像您的情况那样使用n。 ;)


在你的代码中,这个:

char * string = malloc(sizeof(char));

一个字符分配内存,这是不好的,因为即使字符串只有一个字母,你会把空终止符放在哪里?您知道 C 中的字符串应该(几乎)总是以NULL 终止。

要为大小为N 的字符串动态分配内存,您应该这样做:

char * string = malloc((N + 1) * sizeof(char));

N 字符分配空间的位置,加上NULL 终止符的空间。

【讨论】:

  • @BLUEPIXY 我正要更新你所做的,你是个天使。
  • @gsamaras 更好:)
【解决方案2】:

几个问题...

sizeof(char) 一般为 1 个字节。因此 malloc() 只为字符串分配一个字节的内存。也许需要更大的内存块?例如,“Martin”至少需要 6 个字节,加上字符串终止字符(总共 7 个字节)。

printf("%c\n", string[n+1]) 可能不太对...

  String: Martin\0
  strlen= 6
  Offset: 0123456
  n = 5... [n+1] = 6
  The character being output is the string terminator '\0' at index 6.

这可能会更好:

  void printLetter() {

      char * string = malloc(100 * sizeof(char));
      int n;

      printf("Number:\n");
      scanf("%i", &n);
      printf("String:\n");
      scanf("%s", string);

      if(n > strlen(string)) {
          printf("nothing");
      } else {
          printf("%c\n", string[n-1]);
      }

   free(string);


  }

【讨论】:

  • 如果可以只声明 char string[100],为什么还要使用 malloc; ?当字符串长度超过 100 个字符时会发生什么?
  • @DevilaN,我会做很多事情来使这段代码达到我的标准。不幸的是,到那时,问题代码将几乎没有相似之处。我认为最好进行最小的更改,足以让代码运行而不会遇到 scant()、缓冲区大小等问题。
  • 详细信息:“sizeof(char) 一般为 1 字节。”在 C 中,它总是 1 个字节,因为 C 定义了一个 byte
【解决方案3】:

您正面临缓冲区溢出。 看看这个问题,它会告诉你如何在这种情况下正确管理你的内存:How to prevent scanf causing a buffer overflow in C?

或者,您可以询问字母数量并仅分配那么多内存 + 1。然后 fgets(string, n,stdin); 因为您不需要字符串的其余部分:-)

【讨论】:

    猜你喜欢
    • 2017-06-25
    • 1970-01-01
    • 2022-12-20
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 2021-02-24
    • 1970-01-01
    • 2011-12-02
    相关资源
    最近更新 更多