C字符串中的空格?

时间:2014-05-04 00:48:20

标签: c

我在学习用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语句中,它会输出与之前相同的内容,但没有♀。有没有人知道问题可能是什么?我试图打印输入,但似乎空白后的所有文本也终止了。是否允许在字符串中使用空格,如果没有,我该如何解决这个问题呢?

4 个答案:

答案 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'ö') 比较。你可以做以下三件事之一:

  1. 使用回车和续行更清晰地格式化:
  2. 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}}