我使用此代码但无效。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main() {
char line[120], *word;
int o, row, col, letter, i;
o = scanf("%s", line);
row = 0;
while(o != -1) {
col = 0;
while(isprint(line[col])) {
word = (char *) malloc(sizeof(char)*20);
for(i=0; i<20; i++) *(word + i) = 0;
letter = 0;
while(isalpha(line[col])) {
*(word + letter) = line[col];
col++;
letter++;
}
col++;
printf("%s\n", word);
free(word);
}
row++;
o = scanf("%s", line);
}
return 0;
}
例如,我提供输入:
can you take a string?
我作为输出:
can
you
take
a
ke
string
我找不到错误,但输出距离我想要的距离不远意味着错误很小。请帮帮我... :)
答案 0 :(得分:2)
这相当复杂。为什么不用空格字符分隔所有连续的非空格子串呢?
char buf[LINE_MAX];
fgets(buf, sizeof(buf), stdin);
char *end;
const char *seps = " \t\r\n\f\v";
char *p = strtok_r(buf, seps, &end);
printf("%s\n", p);
while (p = strtok_r(NULL, seps, &end))
printf("%s\n", p);
更多建议:
不要重新发明轮子。使用标准库而不是滚动自己的字符串处理(等)函数。它们可以促进您的生活,保证它们是正确的(至少在合理的高质量实现的情况下)并且它们使您的代码更短,从而更具可读性。
当只需要本地(功能范围)存储时,更喜欢自malloc()
以上的自动数组。可变长度数组是自C99以来的标准数组,因此在指定数组大小时,您甚至不需要将自己约束为常量整数表达式。
但如果您决定使用malloc()
,那么至少don't cast its return value。
答案 1 :(得分:1)
我可以建议您稍微改进一下代码吗?
一种已知的安全方式来获取输入而不会使事情变得复杂的是使用fgets(已经指出)。
fgets
允许您指定从控制台获取的字符数,以便不超过缓冲区的限制。
您可以使用fgets
进行用户输入(使用stdin
指针)或从文件中读取(通过提供文件句柄代替stdin
)。
以下是如何简化逻辑的示例:
#include <stdio.h>
int main()
{
char input [100];
/* the [0] bit checks if only a newline has been entered thereby ignoring empty lines */
/* we also check if fgets returns NULL, which may lead to undefined behavior if ignored */
while(fgets(input, 100, stdin) != NULL && input[0] != '\n')
{
int i = 0; /* this counter keeps track of the current char in the input */
int w = 0; /* keep track if we are in a word, fixes printing newline for each white line */
while(input[i] != '\0') /* while we're not at the end of the string */
{
switch(input[i])
{
case ' ': /* if the character is any of the below then print newline */
case '\t':
case '\r':
case '\f':
case '\v':
case '\n':
if (w) { w = 0; printf("\n"); }
break;
default:
if (!w) { w = 1; }
printf("%c", input[i]); /* otheriwse print the character itself */
}
i++;
}
}
return 0;
}
答案 2 :(得分:0)
您似乎认为o = scanf("%s", line);
会引入整行。这是不正确的,它只会读取第一个单词。除了缓冲区溢出和样式问题之外,您的整个程序基本上可以压缩为:
#include <stdio.h>
int main()
{
char line[120];
while(scanf("%s", line) != -1)
{
printf("%s\n", line);
}
return 0;
}
输入:
can you take a string?
输出:
can
you
take
a
string?
如果您真的只想要字母字符,则必须描述其他非空白字符是否也被视为字分隔符,或者是否也被忽略。例如,word1word
打印为word
两次还是wordword
?
假设你想完全忽略非字母,试试这个:
#include <stdio.h>
#include <ctype.h>
void PrintOnlyLetters(char word[])
{
int i;
int count = 0;
for(i = 0; word[i] != '\0'; i++)
{
if(isalpha(word[i]))
{
count++;
printf("%c", word[i]);
}
}
if(count > 0)
{
printf("\n");
}
}
int main()
{
char word[120];
while(scanf("%119s", word) > 0)
{
PrintOnlyLetters(word);
}
return 0;
}
输入:
can yo4u t@ke one (/1) or more string(s)?
输出:
can
you
tke
one
or
more
strings
请注意,虽然这很简单并且无需读取未初始化的内存即可实现您想要的功能,但它仍然很脆弱。例如,它将分解超过119个字符的单词(更改以从代码中删除缓冲区溢出)。