【C/C++】如何帅气地在C/C++中输入字符串

本文详细介绍了C++中多种字符串输入方法,包括scanf、gets、fgets、cin>>、cin.getline()、cin.get()及string类型的输入,探讨了它们的使用方式、细节问题及常见错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. C-风格字符串输入

1.1 scanf

使用 scanf 可以输入不带空格的字符串。

char str[100];
scanf("%s", str);
printf("%s\n", str);

输入: Hello World
输入: Hello

scanf 遇到空格后就会停止读入,余下的部分自动留在缓冲区内。

char str[100];
int i = 1;
while (~scanf("%s", str))
    printf("String %d: %s\n", i++, str);

输入:
Hello World, Everyone!

输入上面一行内容,按下回车键后,会一次性输出三行内容。

输出:
String 1: Hello
String 2: World,
String 3: Everyone!

1.2 gets/fgets

gets

char* gets(char*buffer)

从键盘上输入字符,直至接受到换行符或 EOF 时停止,并将读取的结果存放在 buffer 指针所指向的字符数组中。读入完成后自动在 buffer 末尾添加 \0

注意,即使最后读取到了 \n 符号,也不会把它放入到 buffer 末尾

返回值为 buffer如果 EOF 了,返回 NULL

char str[100];
int i = 1;
while (gets(str))
    printf("String %d: %s\n", i++, str);

输入输出:

Hello World! My friend.
String 1: Hello World! My friend.
Support Vector Machine
String 2: Support Vector Machine

注意到 str 末尾是没有换行符的,gets 把换行符丢弃了!

fgets

gets 在新的 C 标准中被废弃了,原因在于它是不安全的,可以用 fgets 替代。

char * fgets ( char * str, int num, FILE * stream );

需要在 num 参数处指定限制字符数量,然后在 stream 处指定输入流。

fgetsgets 有一个重要的不同。那就是它会保留输入中的换行符

const int MAX_LEN = 20;
char str[MAX_LEN];
int i = 1;
//注意,换行符会被保留
while (fgets(str, MAX_LEN, stdin))
    printf("String %d: %s|\n", i++, str);

输入输出:

Hello World!
String 1: Hello World!
|
I am a boy!
String 2: I am a boy!
|
^Z

终端将被任务重用,按任意键关闭。

1.3 cin >>

1.1.1 使用方式

char sz[20];
cin >> sz;

1.1.2 细节知识点

cin 读取时,它会将回车键生成的换行符保留在缓冲区中。

这点很重要,与之后 getline()get() 函数出现的问题有关。

1.1.3 存在的问题

引例
char sz[20];
char str[20];
cin >> sz;
cin >> str;
cout << sz << endl;
cout << str << endl;

输入

hello world //按回车键

输出

hello
world
原因

cin 使用空白符号来确定字符串结束的位置,这意味着字符数组在输入时一次只读入一个单词。
cin 将该单词放入数组之中,自动添加空字符而输入的其余内容则留在缓冲区中

1.4 cin.getline()

1.2.1 使用方式

istream &getline(char *buffer, streamsize num);
istream &getline(char *buffer, streamsize num, char delim);

getline() 函数用于输入流,读取字符到 buffer 中,直到下列情况发生:

  • num - 1个字符已经读入,
  • 碰到一个换行标志,
  • 碰到一个EOF,
  • 任意地读入,直到读到字符delim。delim字符不会被放入buffer中。
样例
char sz[20];
char str[20];
cin.getline(sz, 20);
cin.getline(str, 20);
cout << sz;//注意没有endl
cout << str << endl;

输入

hello world //按回车键
here //按回车键

输出

hello worldhere
//endl空行

1.2.2 细节知识点

  1. 若参数num为n,则最多读入n-1个字符。
  2. getline() 函数每次读取一行。它通过换行符确定行尾,但不会将换行符留在缓冲区中,而是将换行符用空字符替换保留在字符串中。

以上面的例子为例,在输入hello world之后按下了回车键。

hello world //回车键

但输出时并没有空行。

hello worldhere//没有空行
空行

1.2.3 存在的问题

读入空行
引例

对一下程序

char sz[10];
char str[20];
cin >> sz;
cin.getline(str, 20);
cout << "sz: " << sz << endl;
cout << "str: " << str << endl;
return 0;

首先以一个输入方式为例。

  • 不会出错的输入
her name//按回车键

输出

her
 name//注意前面的空格

cin在读到her后面的空格后结束,并且将空位符留在缓冲区中,由下一个字符串读取。

由此我们可以引出一个常见的错误

  • 会出错的输入
her//按回车键
//无法输入下一个字符串,直接输出

输出

her

这是由于cin将回车键产生的换行符留在缓冲区内所以直接被str读取。 所以str

注意,cin >>cin.getline()连用要小心

而对于cicin.getline()的连用,由于该函数不会将换行符留在缓冲区中,因此连用时没有读取空行的担忧。

也就是说

//这是可行的
cin.getline(sz, 20);
cin.getline(str, 20);
解决办法
cin >> sz;
//法一
cin.get();
//法二,ignore()默认忽略eof标识前一个字符
cin.ignore();
字数超长问题

如果输入行包含的字符比指定的字符数多,getline()会将剩余的字符留在缓冲区中,然后设置失效位,并关闭输入。

1.5 cin.get()

1.3.1 使用方式

原型
int get();
istream &get( char &ch );
istream &get( char *buffer, streamsize num );
istream &get( char *buffer, streamsize num, char delim );
istream &get( streambuf &buffer );
istream &get( streambuf &buffer, char delim );

get()函数被用于输入流,和以下这些:

  • 读入一个字符并返回它的值,
  • 读入一个字符并把它存储在ch,
  • 读取字符到buffer直到num - 1个字符被读入, 或者碰到EOF或换行标志,
  • 读取字符到buffer直到已读入num - 1 个字符,或者碰到EOF或delim(delim直到下一次不会被读取),
  • 读取字符到buffer中,直到碰到换行或EOF,
  • 读取字符到buffer中,直到碰到换行,EOF或delim。(相反, delim直到下一个get()不会被读取 ).

1.3.2 细节问题

2. string 输入

2.1 cin >>

2.1.2 使用方法

同上,一次只能读取一个单词。
注意这里读取时利用while的技巧

int main()
{
	string line;
	ifstream in;
	//每次读取一个单词,直到文件末尾
	while (in >> word)
	{
		cout << word << endl;
	}
	return 0;
}

2.2 getline()

2.2.1 原型

istream& getline (istream&  is, string& str, char delim);
istream& getline (istream&& is, string& str, char delim);

istream& getline (istream&  is, string& str);
istream& getline (istream&& is, string& str);

2.2.2 使用方法

同上,遇到换行符为止(delim),但是终止字符delim(默认为换行符)并不会留在缓冲区中留给下一位来读取,而是变成了空字符留在了字符串中,不影响输出。(可以当作被丢弃了)

2.2.3 例子

有文件a.txt:

Iam a boy
Helloaworld

程序如下:

int main()
{
    ifstream fin("a.txt");
    string str;
    //每次读取一段文字,直到文件末尾EOF
    while (getline(fin, str, 'a'))
    {
        cout << str << endl;
    }
    system("pause");
    return 0;
}

输出结果:

I//遇到了a停止读入
m//字符a没有被读入下一个str
 boy //遇到了a停止读入,但空格被下一个str读入了
Hello
world
### 关于C语言的幽默示例 C语言以其简洁高效而闻名,但也因其灵活性和强大的功能被赋予了许多有趣的用途。下面是一个基于“帅到没朋友”的主题设计的小例子,通过代码展示如何用`goto`语句来表达一种幽默逻辑。 #### 示例代码:帅到没朋友 ```c #include <stdio.h> int main() { int handsome_level = 100; // 帅气等级初始化为100分 start: if (handsome_level >= 90) { printf("你太帅了,朋友们都怕被你的光芒掩盖。\n"); goto lonely; // 如果帅气等级过高,则直接进入孤独状态 } printf("你在努力交朋友...\n"); handsome_level -= 10; // 减少帅气值以便更容易交友 if (handsome_level < 50) { printf("现在你可以轻松交到朋友啦!\n"); return 0; } lonely: // 孤独标签 printf("由于太过帅气,你现在没有朋友。\n"); printf("考虑降低一下自己的魅力吗?\n"); // 给用户一个机会重新调整帅气等级 printf("输入一个新的帅气等级 (<90): "); scanf("%d", &handsome_level); if (handsome_level >= 90) { printf("你还是一如既往地帅,继续孤单吧。\n"); goto end; // 结束程序 } printf("恭喜,你终于找到了平衡之道!\n"); return 0; end: // 程序结束标签 printf("再见,孤傲的大侠。\n"); return 0; } ``` 上述代码利用了`goto`语句创建了一个简单的控制流,模拟了一种夸张的情境——一个人因过于帅气而导致社交困难[^2]。这种写法虽然不推荐用于实际项目开发,但在教学或娱乐场景中却能很好地展现C语言的功能性和趣味性。 --- ### C语言中的其他有趣概念 除了上面提到的例子外,还有许多关于C语言的独特特性和应用值得探索: 1. **指针魔术** 指针是C语言的核心之一,它允许程序员直接操作内存地址。尽管初学者可能会觉得复杂甚至危险,但它也带来了极大的自由度。例如,可以通过指针交换两个变量的值而不借助额外空间: ```c void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } ``` 2. **宏定义的艺术** 宏是一种预处理器指令,能够简化重复性的代码片段。比如可以用宏定义实现一个安全的最大值比较函数: ```c #define MAX(a,b) ((a) > (b) ? (a) : (b)) ``` 3. **数组与字符串的秘密** 字符串在C语言里本质上是以`\0`结尾的一维字符数组。因此可以编写一些巧妙的操作,如下所示打印倒置字符串: ```c void reverse_string(char* str) { if (!str || !(*str)) return; char* end = str; while (*(end + 1)) ++end; while (str < end) { char tmp = *str; *str++ = *end; *end-- = tmp; } } ``` 这些技巧不仅展示了C语言的强大能力,还体现了其背后的哲学思想:让开发者拥有尽可能多的选择权,同时也承担相应的责任。 --- ### 性能对比与其他语言的关系 值得注意的是,在性能方面,C通常被认为是最接近硬件层面的语言之一。相比更高层次的语言(如Java),它的运行效率往往高出数倍[^1]。然而这并不意味着应该忽视现代工具和技术带来的便利;相反,《Essential C++》这样的教材提醒我们关注不同技术栈各自的适用范围及其优劣之处[^4]。 --- 问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值