C++程序崩溃

3
我刚开始学习C ++,下面是我为一项练习编写的程序:
#include <iostream>
#include <string>
using namespace std;

int main ()
{
    int uppercase=0, lowercase=0, digits=0, other=0, i=0;
    int character;
    char* string;
    cout << "Enter a string!\n";
    cin.getline(string, 20); 

    while(true)
        {
        character = int(*(string+i));
        if (character==0)
            {
            break;
            }
        if (character > 64 && character < 91)
            {
            uppercase++;
            }
        if (character > 96 && character < 122)
            {
            lowercase++;
            }
        if (character > 47 && character <58)
            {
            digits++;
            }
        else
            {
            other++;
            }
        i++;
        }

    cout << "Upper case " << uppercase << "\n";
    cout << "Lower case " << lowercase << "\n";
    cout << "Digits " << digits << "\n";
    cout << "Others " << other << "\n";

    return 0;
}

程序在打印结果后崩溃了。这里我是否漏掉了什么非常明显的东西?
此外,一个问题:即使不应该增加变量“other”,它也总是增加。我使用else语句有问题吗?

2
完全离题,但我想指出 <cctype>,它(除其他外)提供了函数 std::isupper()std::islower()std::isdigit()。你正在检查 ASCII 码,一旦出现例如 "José""München" 这样的情况,你将得到错误的结果... - DevSolar
是的...使用std方法检查类型比期望人们知道字符47更不容易出错和混乱。而且更具可移植性;仍有人使用EBCDIC,这段代码在他们身上会彻底失败。以及非英文字母表。 - cHao
实际上,他一开始就不应该使用8位编码,但对于初学者的代码来说,这可能有点过分。;-) - DevSolar
嗯...这个东西我很快就跟不上了。 - RobVerheyen
5个回答

8

您还没有为string分配内存空间。

尝试这样做(在堆栈上分配):

char string[256];

或(在堆上分配):
char* string = new char[256];

delete[] string;

更新

使用 std 和预定义的 isdigit()isalpha() 等函数,可以将代码重写为以下形式:

#include <iostream>
#include <string>

int main ()
{
    int uppercase=0, lowercase=0, digits=0, other=0;

    std::cout << "Enter a string!\n";

    std::string myline;
    std::getline(std::cin, myline);

    for (std::string::iterator i = myline.begin(); i != myline.end(); ++i)
    {
        if (isdigit(*i))
        {
            digits++;
        }
        else if (isalpha(*i))
        {
            isupper(*i) ? uppercase++
                        : lowercase++;
        }
        else
        {
            other++;
        }
    }

    std::cout << "Upper case " << uppercase << "\n";
    std::cout << "Lower case " << lowercase << "\n";
    std::cout << "Digits " << digits << "\n";
    std::cout << "Others " << other << "\n";

    return 0;
}

...... 或者实际上使用std :: string类,因为OP已经包含了头文件。;-) - DevSolar
谢谢。我仍然很难理解指针。在您的第二种解决方案中,“string”仍然是一个指针,但您将其初始化为普通变量,对吗?这相当于首先定义一个空字符串,然后指向它吗?关于字符串类的编辑:我应该按照练习要求这样做。 - RobVerheyen
new 只是分配内存并返回指向已分配块的指针。它们两个(堆栈示例)都定义了一个未定义的字符串。如果您想要一个空字符串,必须显式地将其清空:string[0] = '\0'strcpy(string, "") - huysentruitw
char *string 仍然是一个指针,但这次它指向一个已分配的内存块的有效内存地址。如果你不分配内存,你的指针将指向一个随机的内存块,事情可能会变得非常糟糕(特别是当你覆盖内容时)。 - huysentruitw

3
< p >如果前面的if语句为false,则执行else语句。在您的情况下,当(character > 47 && character <58)为false时,将增加其他。您可能想使用else-if代替:< /p>
if(){
...
}else if{
...
}else if{
...
}else{
...
}

1
你没有为 string 分配内存,使用这个名称可能不是一个好主意:
char* string ;

如果你使用using namespace std,那么可以使用另一种声明方式来避免与std::string重名:

char str[21] ;

在您的代码中,如果您想使用std::string,您需要这样做:
std::string someStringVar ;

因为在声明char *string之后使用这个不起作用:

string someStringVar ;

这似乎违背了使用命名空间std的目的。

1
尝试使用char string[256]代替char* string。我猜getline需要一个指向已分配内存的指针作为输入。

1
正如Open Group的文档所述,“应用程序必须确保lineptr是一个有效的参数,可以传递给free()函数。如果n非零,则应用程序必须确保lineptr指向大小至少为n字节的对象,或者是空指针。”正如free文档所提到的,这意味着string必须由其中一个malloc函数分配。 - Nate Chandler

0

在表示字符时,应该使用char而不是int。这是因为int通常占用4个字节,而char只有1个字节(足以表示一个字符)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接