C 如何读入整个单词,而不仅仅是第一个字符?
我正在用C编写一个方法,其中有一个从stdin重定向的文件中的单词列表。但是,当我尝试将单词读入数组时,我的代码将只输出第一个字符。我知道这是因为char和char*的铸造问题 虽然我在挑战自己不要使用string.h中的任何函数,但我已经尝试迭代并考虑编写自己的strcpy函数,但我感到困惑,因为我的输入来自一个文件,而我正在从标准输入重定向该文件。变量C 如何读入整个单词,而不仅仅是第一个字符?,c,arrays,string,io,char,C,Arrays,String,Io,Char,我正在用C编写一个方法,其中有一个从stdin重定向的文件中的单词列表。但是,当我尝试将单词读入数组时,我的代码将只输出第一个字符。我知道这是因为char和char*的铸造问题 虽然我在挑战自己不要使用string.h中的任何函数,但我已经尝试迭代并考虑编写自己的strcpy函数,但我感到困惑,因为我的输入来自一个文件,而我正在从标准输入重定向该文件。变量numwords由用户在主方法中输入(未显示) 我试图通过dumpwptrs调试此问题,以显示输出内容。我不确定代码中的什么导致我得到错误的输
numwords
由用户在主方法中输入(未显示)
我试图通过dumpwptrs
调试此问题,以显示输出内容。我不确定代码中的什么导致我得到错误的输出——是我如何将单词读入块数组,还是我用WPTR错误地指向它
//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
}
}
//连续存储以null结尾的单词的巨大内存块
字符块[MEMSIZE];
//指向位于块内部的单词
字符*wptrs[MAX_WORDS];
/**词典中的单词总数*/
国际货币基金组织;
.
.
.
无效读字()
{
//读入单词并存储在块数组中
for(int i=0;i
不要重复使用字符块[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
不超过限制
我会选择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;
}
char块[MEMSIZE];
char*pool=chunk;
//返回字数
int readwords2(){
整数字数;
//将字数限制为最大字数
for(单词数=0;单词数<最大单词数;单词数++){
intptr\u t剩余=&chunk[MEMSIZE]-池;
如果(剩余<2){
break;//可用池内存不足
}
if(fgets(池、剩余、标准输入)=NULL){
break;//文件结束/错误
}
池[strcspn(池,“\n”)]='\0';//断开电位\n
wptrs[字数]=池;
池+=strlen(池)+1;
}
返回字数;
}
当我挑战自己不要使用string.h中的任何函数时
挑战自己不要使用string.h
中的任何函数的最好方法是自己编写这些函数,然后使用它们
您的程序在缓冲区块的i
-esim位置读取下一个单词,因此您每次读取时都会得到每个单词的第一个字母(只要i
不超过块的大小),您可以用刚才读过的字符覆盖最后一个单词的第二个字符和其余字符。然后,您将所有指针放在wptrs
中,以指向这些位置,从而无法区分一个字符串的结尾和下一个字符串的结尾(您重写了所有空终止符,只留下最后一个),因此您将得到第一个字符串,其中包含单词的所有第一个字母,但最后一个字母是完整的。然后第二个将有相同的字符串,但从第二个开始。。。然后第三个。。。。等等
构建自己版本的strdup(3)
并使用chunk
临时存储字符串。。。然后用您的strdup(3)
版本创建一个动态分配的字符串副本,并使指针指向它。。。。等等
最后,当您完成时,只需释放所有分配的字符串即可
另外,这一点非常重要:阅读时,您的代码经常会缺少您从发布的代码中消除的一些错误(您通常不知道错误在哪里,或者您会更正错误,这里没有问题,对吗?)在扫描完一个单词后,您希望将该单词的i
字符数增加一个,该单词的0
-终止符可能会增加+1个字符。就目前情况而言,您只增加了i
,您得到的输出很好地反映了这一点。@fassn:No,wptrs
很好。@Inian:No,wptrs
很好。在我看来,似乎每个指针都应该指向数据被扫描到的位置,即chunk
?想想看。如果有必要,可以在纸上画出来。将块
数组绘制为一长串框,每个框包含一个字符。。。。。。。就目前情况而言,您只将i
增加了1,您得到的输出很好地反映了这一点。@alk这非常有用,谢谢dumpwptrs
正在打印正确的输出!