我在学习用C语言编程时遇到了一个问题。我正在创建一个将文本翻译成“rövarspråket”的程序(你不需要了解理解我的问题是什么)。如果我只插入一个单词,程序效果很好,但是当我添加一个空格时,它就会停止生成输出。这是一个例子:
如果我插入“hello world”,我希望输出为“hohelollolo wowororloldod”,而是输出“hohelollolo♀”。这是代码:
int main(){
char inputText[100], outputText[300];
int inputLength, ipTextNum, opTextNum;
scanf("%s", &inputText);
inputLength = strlen(inputText);
for(ipTextNum = 0; ipTextNum < inputLength; ipTextNum++){
if(inputText[ipTextNum] == 'a' || inputText[ipTextNum] == 'e' || inputText[ipTextNum] == 'i' || inputText[ipTextNum] == 'o' || inputText[ipTextNum] == 'u' || inputText[ipTextNum] == 'y' || inputText[ipTextNum] == 'å' || inputText[ipTextNum] == 'ä' || inputText[ipTextNum] == 'ö'){
outputText[opTextNum] = inputText[ipTextNum];
opTextNum++;
}
else {
outputText[opTextNum] = inputText[ipTextNum];
outputText[opTextNum+1] = 'o';
outputText[opTextNum+2] = inputText[ipTextNum];
opTextNum += 3;
}
}
printf("%s", outputText);
return 0;
}
如果我还将inputText [ipTextNum] ==''添加到if语句中,它会输出与之前相同的内容,但没有♀。有没有人知道问题可能是什么?我试图打印输入,但似乎空白后的所有文本也终止了。是否允许在字符串中使用空格,如果没有,我该如何解决这个问题呢?
答案 0 :(得分:2)
问题在这里:
scanf("%s", &inputText);
实际上有两个问题..你想要它读取我假设的整行,所以我们不使用%s,我们使用“除了\ n”之外的所有字符,然后读取\ n。另一个问题是&amp; inputText。
scanf("%s", inputText);
应该如何......但这会增加整行。
scanf("%[^\n]\n", inputText);
继续进行解析,只要你没有溢出!
答案 1 :(得分:1)
scanf
实际上不应该用于带空格的字符串,因为它不接受它们。你应该真的使用fgets
。有关更多信息,请参阅此答案:
https://stackoverflow.com/a/1248017/2990189
以下是一个示例(来自上面的答案),以说明fgets
如何运作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Maximum name size + 1. */
#define MAX_NAME_SZ 256
int main(int argC, char *argV[]) {
/* Allocate memory and check if okay. */
char *name = malloc (MAX_NAME_SZ);
if (name == NULL) {
printf ("No memory\n");
return 1;
}
/* Ask user for name. */
printf("What is your name? ");
/* Get the name, with size limit. */
fgets (name, MAX_NAME_SZ, stdin);
/* Remove trailing newline, if there. */
if ((strlen(name)>0) && (name[strlen (name) - 1] == '\n'))
name[strlen (name) - 1] = '\0';
/* Say hello. */
printf("Hello %s. Nice to meet you.\n", name);
/* Free memory and exit. */
free (name);
return 0;
}
答案 2 :(得分:1)
同时确保输入不会像其他海报所指出的那样溢出缓冲区;另一个主要问题是你永远不会终止你的输出。
printf("%s"
知道何时停止输出字符,因为它遇到空字节。但是你从来没有在输出的末尾写一个空字节,这就解释了为什么在它之后有一个垃圾字符(然后你碰巧在垃圾后的缓冲区中偶然出现一个空字节)。
循环播放后,在outputText[opTextNum] = 0;
之前添加printf
。
当然,您还需要确保循环始终在opTextNum < sizeof outputText
为真时停止。由于input
的最大字符串长度为99
,因此可以写入的最大输出为3*99+1
,因此您可以保证安全。如果您决定稍后更改算法,则需要再考虑一下。
答案 3 :(得分:0)
从表面上看,你的问题是使用scanf
- 它会在遇到的第一个空间停止。使用fgets
通常是答案 - 可能就是这样。还有一个问题是你没有终止你的字符串(这导致了有趣的最后一个字符 - 非常偶然,我必须添加),并且你没有检查输入或输出缓冲区中的溢出。大多数这些观点都是在其他答案中提出的。
然而 - 问题更有趣,也更难,因为您在输入中使用“非ascii”字符。我猜你的劫匪有斯堪的纳维亚人的根源。这意味着您不仅需要担心空白 - 您需要使用“宽字符”。
我冒昧地用“宽”形式重写你的例子 - 这意味着它使用
fgetws - the wide equivalent of fgets
wprintf - the wide equivalent of printf
wcschr - the wide equivalent of strchr
以及L"wide string"
之类的“宽”字符串,L'å'
等“宽”字符以及“宽”格式说明符%ls
。
代码的风格问题是,if
语句非常长OR-ed
,包含与单个字符进行的一系列if( inputText[ipTextNum] == L'a' || \
inputText[ipTextNum] == L'e' || \
inputText[ipTextNum] == L'i' || \
inputText[ipTextNum] == L'o' || \
inputText[ipTextNum] == L'u' || \
inputText[ipTextNum] == L'y' || \
inputText[ipTextNum] == L'å' || \
inputText[ipTextNum] == L'ä' || \
inputText[ipTextNum] == L'ö')
比较。你可以做以下三件事之一:
o
注意:您没有测试空间,因此根据您的描述,空间变为wcschr
,这不是您想要的。
2.用int isVowel(wchar_t c) {
return wcschr("aeiouyåäö ", c)!=0;
}
替换整个事物,查找字符串中的字符;通过搜索元音串中的字符(这是我在下面的代码中所做的 - 包括空间测试);或
3.您也可以为自己创建一个功能,如
#include <stdio.h> // <<<< dont forget your header files
#include <wchar.h> // <<<< to be able to use 'wide' characters: ö etc
// define the max size of input and output string:
#define IP_MAX 100
#define OP_MAX 300
int main(void) { // <<<<< use the correct function signature
wchar_t inputText[IP_MAX], outputText[OP_MAX];
int inputLength, ipTextNum, opTextNum=0; // <<< initialize opTextNum to zero!!
// scanf("%s", &inputText); // <<<< triple NO:
// 1) scanf stops at the first space
// 2) if the input is very long you overwrite your buffer
// 3) you are passing the POINTER to the pointer to char;
// you should use inputText not &inputText
fgetws(inputText, IP_MAX, stdin); // read at most IP_MAX characters into inputText including '\0'
inputLength = wcslen(inputText); // length of wide C string
inputText[--inputLength]='\0'; // strip carriage return
// printf("The length of the string entered is %d\n", inputLength);
wprintf(L"you entered \n'%ls'\n", inputText);
for(ipTextNum = 0; ipTextNum < inputLength && opTextNum < OP_MAX-3; ipTextNum++) {
if(wcschr(L"aeiouyåäö ", inputText[ipTextNum])) { // <<< include test for space too
outputText[opTextNum] = inputText[ipTextNum];
opTextNum++;
}
else {
outputText[opTextNum] = inputText[ipTextNum];
outputText[opTextNum+1] = 'o';
outputText[opTextNum+2] = inputText[ipTextNum];
opTextNum += 3;
}
}
outputText[opTextNum]=L'\0'; // nul terminate the string
wprintf(L"The robber said:\n'%ls'\n\n", outputText);
return 0;
}
使其更加紧凑/可读。
无论如何 - 这是完整的带注释的代码:
hello world
you entered
'hello world'
The robber said:
'hohelollolo wowororloldod'
输出:
{{1}}