如何阅读整个单词,而不仅仅是第一个字符?

时间:2019-06-23 16:28:26

标签: c arrays string io char

我正在用C语言编写一个方法,其中有一个文件的单词列表,该文件是从标准输入重定向的。但是,当我尝试将单词读入数组时,我的代码将仅输出第一个字符。我了解这是因为char和char *的转换问题。

虽然我在挑战自己不要使用string.h中的任何函数,但我尝试进行迭代并考虑编写自己的strcpy函数,但由于输入来自我自己的文件而感到困惑从标准输入重定向。变量numwords由用户在main方法(未显示)中输入。

我正在尝试通过dumpwptrs调试此问题,以告诉我输出是什么。我不确定代码中的内容是什么导致我得到错误的输出-是通过字读取块数组的方式还是用wptrs错误地指向它?

//A huge chunk of memory that stores the null-terminated words contiguously
char chunk[MEMSIZE]; 

//Points to words that reside inside of chunk
char *wptrs[MAX_WORDS]; 

/** Total number of words in the dictionary */
int numwords;
.
.
.
void readwords()
{
  //Read in words and store them in chunk array
  for (int i = 0; i < numwords; i++) {
    //When you use scanf with '%s', it will read until it hits
    //a whitespace
    scanf("%s", &chunk[i]);
    //Each entry in wptrs array should point to the next word 
    //stored in chunk
    wptrs[i] = &chunk[i]; //Assign address of entry
  }
}

2 个答案:

答案 0 :(得分:2)

请勿重复使用先前词中的char chunk[MEMSIZE];

请使用下一个未使用的内存。

char chunk[MEMSIZE]; 
char *pool = chunk; // location of unassigned memory pool

    // scanf("%s", &chunk[i]);
    // wptrs[i] = &chunk[i];
    scanf("%s", pool);
    wptrs[i] = pool;
    pool += strlen(pool) + 1;  // Beginning of next unassigned memory

严格的代码将检查scanf()的返回值,并确保i, chunk不超过限制。

只要每次输入 word 行,我都会寻求fgets()解决方案。

char chunk[MEMSIZE]; 
char *pool = chunk;

// return word count
int readwords2() {
  int word_count;
  // limit words to MAX_WORDS
  for (word_count = 0; word_count < MAX_WORDS; word_count++) {
    intptr_t remaining = &chunk[MEMSIZE] - pool;
    if (remaining < 2) {
      break; // out of useful pool memory
    }
    if (fgets(pool, remaining, stdin) == NULL) {
      break; // end-of-file/error
    }
    pool[strcspn(pool, "\n")] = '\0'; // lop off potential \n
    wptrs[word_count] = pool;
    pool += strlen(pool) + 1;
  }
  return word_count;
}

答案 1 :(得分:0)

  

尽管我在挑战自己不要使用string.h中的任何功能,...

不使用string.h中的任何功能来挑战自己的最佳方法是自己编写然后使用它们。

您的程序读取缓冲区i的{​​{1}}-esim位置中的下一个单词,因此您将获得每个单词的第一个字母(只要chunk不每次阅读都超过i的大小时,您用刚读过的单词覆盖了最后一个单词的第二个字符和其余字符。然后,将所有指针放在chunk中以指向这些位置,从而无法将一个字符串的末尾与下一个字符串区分开(您覆盖了所有空终止符,仅保留了最后一个),因此您将获得第一个字符串,包含单词中所有单词的首字母,但最后一个字母完整。那么第二个将具有相同的字符串,但是从第二个开始……然后是第三个……等等。

构建您自己的wptrs版本,并使用strdup(3)临时存储字符串...然后使用您的chunk版本动态创建该字符串的副本,并创建指针指向它...。等等。

最后,当您完成操作后,只需释放所有分配的字符串并voilà!!

这也非常重要:请阅读How to create a Minimal, Complete, and Verifiable example,因为您的代码经常缺少一些已从已发布的代码中消除的错误(您通常不知道错误在哪里,或者您会更正它,在这里没有问题吧?)