【问题标题】:Simple word comparison in CC中的简单单词比较
【发布时间】:2014-12-22 18:51:41
【问题描述】:

我刚刚用 C 语言编写了一个相当简单的程序来查找 smallest wordlargest word。我有 3 个变量如下:

char smallest[20]; // smallest word
char largest[20]; // largest word
char word[20]; // the word entered by user

然后我会提示用户输入他想要的任何单词:

while (1) {
  printf("Enter a word: ");
  while((ch = getchar()) != '\n') {
    word[i++] = ch;
  }
}

然后我将wordsmallestlargest进行比较,以达到在用户输入的单词中找到最小和最大单词的结果。

if (strcmp(word, smallest) < 0) {
  strcpy(smallest, word);
}

if (strcmp(word, largest) > 0) {
  strcpy(largest, word);
}

最后,如果用户不输入任何单词就直接输入,程序将终止。 该程序正确找到largest 字,但我的问题是找到smallest 字。

如果你想复制/粘贴来测试它,这里是整个程序。

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

int main(void) {

  char smallest[20] = "";
  char largest[20] = "";
  char word[20] = "";

  while (1) {

      int i = 0;
      char ch;

      strcpy(word, "");

      printf("Enter a word: ");
      while((ch = getchar()) != '\n') {
        word[i++] = ch;
      }

      if (strcmp(word, smallest) < 0) {
        strcpy(smallest, word);
      }

      if (strcmp(word, largest) > 0) {
        strcpy(largest, word);
      }


    if (strlen(word) == 0) break;
  }

  printf("Smallest word: %s\n", smallest);
  printf("Largest word: %s\n", largest);

  return 0;

}

请告诉我如何修改它以正确找到smallestlargest 字词。

【问题讨论】:

  • 字符是否最大 = "";错字?你的意思是 char large[20] = "";?
  • 这是我不知道如何以及何时正确初始化它们
  • 您需要将输入的第一个单词直接复制到最小,因为空字符串比较“小于”任何其他字符串,因此您已将smallest_word 初始化为可能的最小单词。您可以改用更复杂的初始化,例如memset(smallest, '\xFF', sizeof(smallest)-1); smallest[sizeof(smallest)-1] = '\0';;这是适合 20 字节缓冲区的“最大”字(以空字符结尾的字符串)。如果代码遇到EOF,您也会遇到问题;你的循环继续,你必须中断这个程序来停止它。
  • @JonathanLeffler,我在正确初始化 smallestlargest 时遇到问题。谢谢你的好点
  • 1) 最佳初始化方法 char variable[20] = {'\0'};但是,在保存新单词之前需要重新初始化它(可能通过 memset()),因此缓冲区中没有剩余的垃圾。 2) 读取单词的循环没有大小限制,因此如果用户输入的单词超过 19 个字符,则会发生缓冲区溢出,这可能/将导致 seg fault 事件。

标签: c


【解决方案1】:

这个循环至少有四个问题:

  while((ch = getchar()) != '\n') {
    word[i++] = ch;
  }

首先它可以覆盖数组之外的内存,其次你必须在字符串后面加上终止零。此外,您将结果保存到chargetchar() 返回int,并且您没有测试EOF,但您应该(使用int ch; 至关重要,这样您就可以准确地测试@ 987654327@).

使用函数 fgets 而不是 getchar(但请记住它在其输出中包含换行符)。

或者按照下面的方式重写循环

  while( i < 19 && (ch = getchar()) != '\n' && ch != EOF) {
    word[i++] = ch;
  }

  word[i] = '\0';

考虑到您的代码中似乎存在拼写错误。至少我没有看到声明 smallest_wordlargest_word

【讨论】:

  • @Jonathan Leffler 感谢您的帮助。:)
【解决方案2】:

您的一个问题是,空字符串比较小于所有其他字符串,因此您找到最小字符串的代码正确返回了初始化它的空字符串。

由于没有比所有其他字符串都大的特殊字符串,因此您需要使用获得的第一个字符串作为初始化:

for(int i = 0; ; i++) {

    //code to read a string

    if(!i) {
        //First time: the current string is definitely the smallest and the largest one.
        strcpy(smallest, word);
        strcpy(largest, word);
    } else {
        if (strcmp(word, smallest_word) < 0) strcpy(smallest, word);
        if (strcmp(word, largest_word) > 0) strcpy(largest, word);
    }
}

旁注:
使用固定大小的缓冲区来存储来自用户输入的字符串通常不是一个好主意。迟早你得到一个超过你的缓冲区大小的输入。更好地使用动态分配的字符串。在你的情况下,你可以这样做:

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

int main(void) {
  char* smallest = NULL, *largest = NULL, *word = NULL;

  for(int i = 0; ; i++) {
      printf("Enter a word: ");
      size_t bufferSize = 0;
      ssize_t stringSize = getline(&word, &bufferSize, stdin);    //this returns a malloced string with the entire line in word
      if(stringSize <= 0) break;    //This also catches end of file.
      word[stringSize - 1] = 0;    //getline() includes the newline in the string, remove it

      if(!i) {
          //First time: the current string is definitely the smallest and the largest one.
          smallest = strdup(word);
          largest = strdup(word);
      } else {
          if (strcmp(word, smallest) < 0) {
              free(smallest);
              smallest = strdup(word);
          }
          if (strcmp(word, largest) > 0) {
              free(largest);
              largest = strdup(word);
          }
      }

      free(word);
  }

  printf("Smallest word: %s\n", smallest);
  printf("Largest word: %s\n", largest);

  free(smallest);
  free(largest);

  return 0;

}

用户可以在这段代码中抛出长度为兆字节的字符串,它会轻松处理它们。

【讨论】:

  • getline() 并非随处可用
  • getline() 通常被实现为包括尾随换行符,然后是 '\0' 咬。代码可能想用 '\0' 替换换行符
  • @user3629249 好点。我修复了代码。是的,getline()strdup() 符合 POSIX-2008 标准,该标准并未在任何地方实施。
【解决方案3】:

使用strlen() 而不是strcmp() 来查看哪个单词更长。 strcmp() 会比较两个字符串是否相同,strlen() 会得到长度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多