简体   繁体   English

程序仅在C ++中打印数组中的前三个字符

[英]Program prints only first three characters in array in C++

My program is to read characters into an array and display it to the console. 我的程序是将字符读入数组并将其显示在控制台上。 But I don't know why it only reads first 3 characters. 但是我不知道为什么它只读取前3个字符。

#include <iostream>

using namespace std;
int main() {    
    int length=0,i;
    char str[10];
    cout<<"Enter a string"<<"\n";

    for(i=0; str[i] != '\0'; i++) {
        cin>>str[i];
    }

    for(int i=0; str[i]!='\0'; i++) {
        cout<<str[i];
        length++;
    }
    cout<<"\n"<<"Length of the string="<<""<<length<<"\n";
}

The output looks like: 输出如下:

在此处输入图片说明

Here are some of the issues I noticed: 这是我注意到的一些问题:

  1. You're checking the contents of str before you even initialize it. 您甚至在初始化str之前都要检查str的内容。
  2. You're assuming the string you're fetching from the stream will be null-terminated, but that's actually not the case. 您假设要从流中获取的字符串将以空值结尾,但实际上并非如此。
  3. You aren't checking whether cin is working correctly 您没有检查cin是否正常工作
  4. You don't check to make sure the string is 10 characters or less, this could cause you to overflow past the end of the buffer 您不检查字符串长度是否小于或等于10个字符,否则可能会导致缓冲区溢出
  5. When you're checking the length of the array, again you assume the string is null-terminated 当您检查数组的长度时,再次假设该字符串以null终止

If you want to fix these issues and still use a char buffer, see user4581301's comprehensive answer. 如果要解决这些问题并仍然使用char缓冲区,请参阅user4581301的综合解答。 However, I'd suggest simply switching to std::string. 但是,我建议您简单地切换到std::string. For example: 例如:

#include<iostream>

using namespace std;

int main()
{
    string str;
    cout<<"Enter a string"<<"\n";
    if (cin >> str) {
        cout << str << endl;
        cout << "Length of the string = " << str.length() << endl;
    }
}

TL;DR version TL; DR版本

std::string str; //use std::string. practically no reasons not to in C++
if (cin >> str) // read into string and test that read succeeded.
{
    std::cout << str << '\n'
              << "Length of the string=" << str.length() << endl;
}

Explaining and salvaging Asker's version 解释和挽救Asker版本

for(i=0; str[i] != '\0'; i++){ // str[i] tested here
    cin>>str[i]; // but it has no assigned value until here.

uses str[i] before it is assigned a value. 在为其赋值之前使用str[i] The program likely found a null character in the block of memory allocated for str and stopped prematurely, but technically anything can happen if you use an uninitialized variable. 该程序可能在为str分配的内存块中找到了一个空字符,并过早停止了该程序,但从技术上讲,如果使用未初始化的变量,则可能会发生任何事情。 For example, you got the expected result 3 times before finding the null. 例如,在找到空值之前,您获得了3次预期结果。 The program could never found a null and run forever. 该程序永远找不到空值并永远运行。 It could have rained unicorns. 可能会下雨的独角兽。 Anything. 没事

int i = 0;
do {
    cin>>str[i];
} while (str[i++] != '\0');

reads then tests. 然后读取测试。 But lines of data in a stream are not C-style strings and are not terminated with null. 但是流中的数据行不是C样式的字符串,也不以null终止。

int i = 0;
do {
    cin>>str[i];
} while (!std::isspace(str[i++]));

exits when whitespace is found, typically signalling the end of a word, rather than null. 找到空白时退出,通常表示单词的结尾,而不是null。

But what if cin>>str[i]; 但是如果cin>>str[i];怎么办cin>>str[i]; failed for some reason? 由于某种原因而失败?

int i = 0;
do {
    cin>>str[i];
} while (cin && !std::isspace(str[i++]));

Adds a test to ensure something was read. 添加测试以确保已读取某些内容。 But what if there are more than 10 characters and char str[10]; 但是,如果有超过10个字符和char str[10];该怎么办char str[10]; is overflowed? 溢出了吗?

int i = 0;
do {
    cin>>str[i];
} while (cin && !std::isspace(str[i]) && ++i < sizeof(str));

unless I am reading That is legal unless I'm reading [expr.cond] and [expr.log.and] wrong, sequencing of when ++i occurs in !std::isspace(str[i]) && ++i < sizeof(str)) is guaranteed to not affect !std::isspace(str[i]) 除非我正在阅读那是合法的,除非我正在阅读[expr.cond][expr.log.and]错误,否则++i何时在!std::isspace(str[i]) && ++i < sizeof(str))出现的顺序!std::isspace(str[i]) && ++i < sizeof(str))保证不影响!std::isspace(str[i])

But what if you run out of space before find the null? 但是,如果在找到null之前空间不足,该怎么办? str is unterminated and not a string! str是未终止的,不是字符串! This ruins the for loop later in the program. 这破坏了程序后面的for循环。

int i = 0;
do {
    cin>>str[i];
} while (cin && !std::isspace(str[i]) && ++i < sizeof(str));
if (i == sizeof(str))
{
    str[sizeof(str)-1] = '\0';
}

I think that covers everything you're likely to run into here. 我认为这涵盖了您可能会遇到的所有问题。

You read in character by character and store it in str[i] ; 您逐字阅读,并将其存储在str[i] but then you increment i++ before checking str[i]!='\\0' . 但是然后在检查str[i]!='\\0'之前先递增i++

There are two issues with this approach: First, you check a value at a position that has not been written at that point in time. 这种方法有两个问题:首先,您在该时间点尚未写入的位置检查值。 Second, cin>>str[i] will never write the string termination character - it just reads in valid characters, and if input is terminated (eg by EOF), nothing is written. 其次, cin>>str[i]永远不会写入字符串终止字符-它只会读取有效字符,并且如果输入终止(例如,通过EOF),则不会写入任何内容。

So you are approaching this the wrong way. 因此,您正以错误的方式进行处理。

If you want to read at most 10 characters up to a new line (ie when the user presses enter), use fgets . 如果要最多读取10个字符直到换行(即,当用户按下Enter键时),请使用fgets Or - and this is the preferred option - use cin and write into an std::string -object. 或者-这是首选选项-使用cin并写入std::string -object。

int main()
{
    std::string str;
    cin >> str;
    std::cout << str << std::endl;
}

str [i]!='\\ 0'检查存储在str [i]的现有数据,而不是用户输入的值。

Add string initialization: 添加字符串初始化:

char str[10] = {'\0'};

and change the reading with: 并使用以下命令更改读数:

char c;
for(int i = 0; cin>> c && c!=/*add your termination cond. here*/ && i < 10;++i)
    str[i] = c;

So you can ensure that the string is filled with correct values and terminated appropriately. 因此,您可以确保用正确的值填充字符串并适当地将其终止。

But better solution would be to use std::string . 但是更好的解决方案是使用std :: string In that case you dont have to check the sizes, because the string grows by itself.For example: 在这种情况下,您不必检查大小,因为字符串本身会增长,例如:

    std::string str;
    for(char c; cin>>c && c!=/*add your termination cond. here*/;) 
        str += c;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM