【问题标题】:Characters after a space is not being printed out空格后的字符没有被打印出来
【发布时间】:2020-09-02 03:09:37
【问题描述】:

我使用字符数组从用户那里获取输入,然后显示输出。但是,每次我输入中间有空格的值时,只会打印空格前的第一个单词。

例如,这是我输入的:

Customer No.:7877 323 2332

这将是输出:

Customer No.:7877

我已经搜索了可能的解决方案,但似乎找不到合适的解决方案。

这是我的参考代码:

#include<iostream>
using namespace std;

int main()
{
    char custNum[10] = " ";  // The assignment does not allow std::string
    
    cout << "Please enter values for the following: " << endl;
    cout << "Customer No.: ";
    cin >> custNum;
    
    cout << "Customer No.: " << custNum << endl;
}

【问题讨论】:

  • 不使用 std::string 的任何特殊原因?
  • @d4rk4ng31,我们被要求暂时不要使用它。如果可以的话会容易得多。
  • 嗯....好吧,无论如何,尝试使用char* str = new char[1]; scanf("%[^\n]s",str); 代替
  • Don't SKIMP on buffer size (e.g. char custNum[32]) to read the line as a string requires a minimum of 14 characters (double that and take the next power of two for a粗略的破解)
  • 这能回答你的问题吗? Reading string from input with space character?

标签: c++ arrays char character limit


【解决方案1】:

另一种选择是使用std::basic_istream::getline 将整个字符串读入缓冲区,然后使用简单的for 循环删除空格。但是当使用普通的旧字符数组时不要吝啬缓冲区大小。 1000 个字符太长比 1 个字符太短要好得多。通过您的输入,您的绝对最小大小 custNum14 字符(显示的 13 加上 '\0'(nul 终止)字符。(粗略的经验法则,采用您最长估计的输入并加倍它——允许用户错误、猫踩键盘等...)

在你的情况下,你可以简单地做:

#include <iostream>
#include <cctype>

int main() {
    
    char custNum[32] = " ";  // The assignment does not allow std::string
    int wrt = 0;
    
    std::cout << "Please enter values for the following:\nCustomer No.: ";
    
    if (std::cin.getline(custNum, 32)) {    /* validate every input */
    
        for (int rd = 0; custNum[rd]; rd++)
            if (!isspace((unsigned char)custNum[rd]))
                custNum[wrt++] = custNum[rd];
        custNum[wrt] = 0;
        
        std::cout << "Customer No.: " << custNum << '\n';
    }
}

两个循环计数器rd(读取位置)和wrt(写入位置)仅用于循环原始字符串并删除找到的任何空格,当循环离开时再次以nul终止。

使用/输出示例

$ ./bin/readcustnum
Please enter values for the following:
Customer No.: 7877 323 2332
Customer No.: 78773232332

还可以查看Why is “using namespace std;” considered bad practice?C++: “std::endl” vs “\n”。现在养成好习惯比以后改掉坏习惯要容易得多……仔细检查一下,如果您有任何问题,请告诉我。

【讨论】:

    【解决方案2】:

    除了std::getline,如果你打算使用C风格的字符串,试试下面的代码:

    int main() {
        char* str = new char[60];
        scanf("%[^\n]s", str);  //accepts space a a part of the string (does not give UB as it may seem initially
        printf("%s", str);
        return 0;
    }
    

    另外,如果你绝对需要它是一个数字,那么使用atoi

    int ivar = std::atoi(str);
    

    PS 不要忘记得到(!!危险!!)

    char* str;
    gets(str);
    puts(str);
    

    【讨论】:

    • 现在关于那个错位的's':)man 3 scanfC11 Standard - 7.21.6.2 The fscanf function(p12)
    • @DavidC.Rankin 认真的人。现在你只是在找我:(stackoverflow.com/a/6282396
    • @Quinton417,不要忘记点击那个小复选标记并接受对你有用的答案
    • 另外,请查看@DavidC.Rankin 的回答。它比我的好:)
    • 谢谢。我想你指的是你上面链接的答案下面的评论? 's' 正如您所拥有的那样,它将寻求匹配输入中的文字 's',但由于没有进行转换,并且由于之前发生了成功的转换,因此没有 匹配失败输入失败 结果。它将做的是防止任何后续的转换说明符匹配。尝试匹配scanf("%[^\n]s%d", str, &amp;i),然后匹配scanf("%[^\n]%d", str, &amp;i)(需要多行输入)
    【解决方案3】:

    cin &gt;&gt; int_variable 将在到达第一个不是数字有效部分的字符时停止读取输入。 C++ 不会将空格视为数字的一部分,因此它会在遇到空格时立即停止读取。

    您可以改用std::getline 读入字符串,然后在转换为整数之前从字符串中删除空格。或者在这种情况下,您甚至不需要整数,可以将其保留为字符串。

    【讨论】:

    • OP 没有读取int 变量。虽然它被称为“custNum”,但声明的类型是char 的数组。我认为目的是存储格式化的数字(保留空格)。
    • @JaMiT custNum 的定义被编辑到问题中,我第一次看到它时不得不猜测。
    • 更准确地说,它已恢复到问题中,但确实,它已经消失了一段时间(不到一个小时 - 实际上它在您发布此答案之前已恢复)。这就是为什么我发布了一个温和的提示,而不是说你没有回答这个问题。此外,只需进行一些调整即可使此答案与问题相符。
    • @JaMiT 很有趣,这就是我没有查看 整个 编辑历史的结果。不幸的是,我没有太多使用 &gt;&gt; 读取字符串的经验,所以我没有信心编辑我的答案以准确地使用这些新信息。
    猜你喜欢
    • 1970-01-01
    • 2013-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多