首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >洛谷题单:【入门5】字符串->“P1957 口算练习题“(多法实现+语法讲解)

洛谷题单:【入门5】字符串->“P1957 口算练习题“(多法实现+语法讲解)

作者头像
序属秋秋秋
发布2025-12-18 14:57:55
发布2025-12-18 14:57:55
1810
举报
洛谷题单:【入门5】字符串->"P1957 口算练习题"(多法实现+语法讲解)


👨‍💻 博主正在持续更新编程习题中。 ❤️ 如果你觉得内容还不错,请多多点赞。 ⭐️ 如果你觉得对你有帮助,请多多收藏。(防止以后找不到了) 👨‍👩‍👧‍👦如果你想阅读更多的编程习题讲解和C++的语法讲解,请多多关注博主。


在这里插入图片描述
在这里插入图片描述

往期练习题回顾: 链接: P5733 【深基6.例1】自动修正 P1914 小书童——凯撒密码 P1125 [NOIP2008 提高组] 笨小猴


题目介绍

在这里插入图片描述
在这里插入图片描述

方法一:

代码展示

代码语言:javascript
复制
#include <iostream> 
#include <cstring> //使用memset 和 strlen 
#include <cstdio> //使用sscanf 和 sprintf 
using namespace std;

int main()
{
	char operatorChar;
	int num1, num2;
	char input[10], resultString[100];

	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> input;
		//如果输入的第一个是字符,即运算符
		if (input[0] >= 'a' && input[0] <= 'z')
		{
			operatorChar = input[0];
			cin >> num1 >> num2;
		}
		//如果输入的第一个是数字,即操作数
		else
		{
			sscanf(input, "%d", &num1);
			cin >> num2;
		}
        	
		memset(resultString, 0, sizeof(resultString));//清空原有的字符串,防止长度判断错误
		switch (operatorChar)
		{
		case 'a':
			sprintf(resultString, "%d+%d=%d", num1, num2, num1 + num2);
			break;
		case 'b':
			sprintf(resultString, "%d-%d=%d", num1, num2, num1 - num2);
			break;
		case 'c':
			sprintf(resultString, "%d*%d=%d", num1, num2, num1 * num2);
			break;
		}
		cout << resultString << endl << strlen(resultString) << endl;
	}
	return 0;
}

交互过程: 4 a 1 2 1+2=3 5 3 4 3+4=7 5 b 5 6 5-6=-1 6 c 7 8 7*8=56 6

核心模块

根据输入值的类型选择将其存入不同的变量中
代码语言:javascript
复制
cin >> input;
//如果输入的第一个是字符,即运算符
if (input[0] >= 'a' && input[0] <= 'z')
{
	operatorChar = input[0];
	cin >> num1 >> num2;
}
//如果输入的第一个是数字,即操作数
else
{
	sscanf(input, "%d", &num1);
	cin >> num2;
}
将一些基本数据类型的变量合并成字符串
代码语言:javascript
复制
int num1;
int num2;

sprintf(resultString, "%d+%d=%d", num1, num2, num1 + num2);

sprintf(resultString, "%d-%d=%d", num1, num2, num1 - num2);

sprintf(resultString, "%d*%d=%d", num1, num2, num1 * num2);

语法讲解

sscanf函数

函数的介绍 sscanf:用于从字符串中读取格式化的数据。

  • 它是从 C 语言继承而来的中的一个函数,是 scanf 函数的字符串版本。
    • scanf 是从标准输入(通常是键盘)读取数据。
    • sscanf 是从一个指定的字符串中读取数据。
  • 它主要用于将字符串中的数据按照指定的格式解析出来,并存放到变量中。
  • 如果 sscanf 用于读取字符串到字符数组中,需要确保数组有足够的空间来存储读取的数据,包括终止的空字符。

函数的原型

代码语言:javascript
复制
int sscanf(const char *str, const char *format, ...);
  • str:是要读取数据的字符串。
  • format:是格式控制字符串。
    • 指定了后续参数的类型和如何从字符串 str 中解析这些参数。
    • 这个格式字符串与 scanf 使用的格式字符串非常相似。
  • ...:是可变参数列表。
    • 一个可变数量的参数。
    • 用于接收从字符串中读取出来的数据并存储到相应的变量中。

函数的使用

读取整数

代码语言:javascript
复制
int num; 
char str[] = "123"; 
sscanf(str, "%d", &num);
  • %d:用于读取一个十进制整数。
    • sscanf函数会将字符串str中的数字123解析出来。
    • 并存储到变量num中。

读取浮点数

代码语言:javascript
复制
float f; 
char str[] = "3.14"; 
sscanf(str, "%f", &f);
  • %f:用于读取一个浮点数。
    • sscanf函数会将字符串str中的3.14解析为浮点数。
    • 并存储到变量f中。

读取字符串

代码语言:javascript
复制
char sub_str[10]; 
char str[] = "Hello World"; 
sscanf(str, "%s", sub_str);
  • %s:用于读取一个字符串。
    • sscanf函数会将字符串str中的第一个单词Hello读取出来,
    • 并存储到变量sub_str中。
    • 注意:%s遇到空格就会停止读取。

读取多个数据

代码语言:javascript
复制
int a, b; 
char str[] = "10 20"; 
int n = sscanf(str, "%d %d", &a, &b);
  • sscanf会按照顺序将str中的10读取到a中,20读取到b中。

函数的返回值

sscanf函数返回:成功读取并赋值的参数的个数。

代码语言:javascript
复制
int a, b; 
char str[] = "10 20"; 
int n = sscanf(str, "%d %d", &a, &b);
  • 如果读取成功。n的值为2,因为成功读取并赋值了两个变量。
  • 如果格式不匹配或者读取过程中出现错误。返回值可能小于期望读取的变量个数。
  • 例如:
    • 如果str"10x"n的值可能为1
    • 因为只有第一个%d成功读取了10
    • 遇到x时第二个%d无法正确读取。

sprintf函数

函数的介绍 sprintf:用于将格式化的数据写入字符串。

  • 它是从 C 语言继承而来的中的一个函数,是 sprintf 函数的字符串版本。
    • printf 是将格式化的输出发送到标准输出(通常是屏幕)
    • sprintf 是将输出发送到一个字符串缓冲区。

函数的原型

代码语言:javascript
复制
int sprintf(char *str, const char *format, ...);
  • str:是一个字符数组的指针,即目标字符串缓冲区。
    • sprintf 会将格式化的输出写入这个缓冲区。
  • format:是格式控制字符串。
    • 指定了后续参数的类型和如何格式化这些参数。
    • 这个格式字符串与 printf 使用的格式字符串非常相似。
  • ...:是可变参数列表。
    • 一个可变数量的参数。
    • 包含要进行格式化的数据。

函数的使用

格式化整数

代码语言:javascript
复制
char buffer[50]; 
int num = 123; 
sprintf(buffer, "The number is %d", num);
  • %d:用于格式化整数。
    • sprintf函数会将num的值(即 123)按照指定的格式写入到buffer字符串中。
    • 最终buffer的内容变为The number is 123

格式化浮点数

代码语言:javascript
复制
char buffer[50]; 
float f = 3.14; 
sprintf(buffer, "The float number is %f", f);
  • %f:用于格式化浮点数。
    • sprintf函数会将f的值(即3.14)按照指定的格式写入到buffer字符串中。
    • 最终buffer的内容变为The float number is 3.140000

格式化字符串

代码语言:javascript
复制
char buffer[50]; 
char str[] = "Hello"; 
sprintf(buffer, "The string is %s", str);
  • %s:用于格式化字符串。
    • sprintf函数会将str的内容(Hello)按照指定的格式写入到buffer字符串中。
    • 最终buffer的内容变为The string is Hello

组合多种数据类型

代码语言:javascript
复制
char buffer[100]; 
int a = 10; 
float b = 2.5; 
sprintf(buffer, "Integer: %d, Float: %f", a, b);
  • sprintf函数会将ab的值按照指定格式写入到buffer字符串中。
  • 最终buffer的内容变为Integer: 10, Float: 2.500000

函数的返回值

sprintf函数返回:成功写入到目标字符串中的字符数(不包括字符串结束符\0)。

代码语言:javascript
复制
char buffer[50]; 
int num = 123; 
int n = sprintf(buffer, "The number is %d", num);
  • n的值为17(因为The number is 123这个字符串的长度为 17)。
memset函数

函数的介绍 memset :将一段内存空间的每个字节都设置为指定的值。

  • 它是 C/C++ 中的一个内存操作函数。
  • 它被包含在 <cstring> 头文件中。
  • 它通常用于通常用于初始化数组、结构体等数据结构,将它们的内存内容快速清零或者设置为某个特定的值。
  • 它常用于初始化数组或结构体,但只能设置固定值,对于复杂的初始化逻辑,应该使用循环或其他初始化方法。

函数的原型

代码语言:javascript
复制
void *memset(void *ptr, int value, size_t num);
  • ptr:是指向要操作的内存块的起始地址的指针。
  • value:是要设置的字节值。
    • 虽然参数类型是 int,但是实际这个值会被转换为unsigned char类型后填充到内存块中。
  • num:要设置的字节数。
    • 也就是从ptr开始的内存长度。

函数的使用

完全初始化数组

代码语言:javascript
复制
char buffer[100]; 
memset(buffer, 'A', sizeof(buffer));
  • 这会将buffer数组的 100 个字节都设置为字符A,实际上就是将整个数组的内容都初始化为A

部分初始化数组

代码语言:javascript
复制
int largeArr[1000];
memset(largeArr, 0, 100);
  • 如果只想初始化前 100 个字节(假设int占 4 个字节,那么就是前 25 个元素)
  • 可以使用memset(largeArr, 0, 100);

初始化结构体

代码语言:javascript
复制
struct Student {
    char name[20];
    int age;
    float score;
};
                  
Student stu;
memset(&stu, 0, sizeof(Student));
  • 这会将结构体stu的所有成员的内存都初始化为 0
  • 即将name数组清零,age设为 0,score设为 0.0

方法二:

代码展示

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <cctype>  // 使用 isalpha
#include <cstdlib> // 使用 atoi
using namespace std;

int main() {

	char operatorChar;
	int num1, num2;
	string input, resultString;

	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> input;
		if (isalpha(input[0]))
		{
			operatorChar = input[0];
			cin >> num1 >> num2;
		}
		else
		{
			num1 = atoi(input);
			cin >> num2;
		}

		switch (operatorChar)
		{
		case 'a':
			resultString = to_string(num1) + "+" + to_string(num2) + "=" + to_string(num1 + num2);
			break;
		case 'b':
			resultString = to_string(num1) + "-" + to_string(num2) + "=" + to_string(num1 - num2);
			break;
		case 'c':
			resultString = to_string(num1) + "*" + to_string(num2) + "=" + to_string(num1 * num2);
			break;
		}
		cout << resultString << endl << resultString.size() << endl;
	}
	return 0;
}

交互过程: 4 a 1 2 1+2=3 5 3 4 3+4=7 5 b 5 6 5-6=-1 6 c 7 8 7*8=56 6

核心模块

根据输入值的类型选择将其存入不同的变量中
代码语言:javascript
复制
cin >> input;
//如果输入的第一个是字符,即运算符
if (isalpha(input[0]))
{
	operatorChar = input[0];
	cin >> num1 >> num2;
}
//如果输入的第一个是数字,即操作数
else
{
	num1 = atoi(input);
	cin >> num2;
}
将一些基本数据类型的变量合并成字符串
代码语言:javascript
复制
int num1;
int num2;

resultString = to_string(num1) + "-" + to_string(num2) + "=" + to_string(num1 - num2);

resultString = to_string(num1) + "-" + to_string(num2) + "=" + to_string(num1 - num2);

resultString = to_string(num1) + "*" + to_string(num2) + "=" + to_string(num1 * num2);

语法讲解

atoi函数

函数的介绍 atoi :用于将字符串(const char* 类型)转换为整数(int 类型)。

  • 该函数在<cstdlib>头文件中声明。
  • 它会尝试将一个以'\0'结尾的字符串转换为对应的整数值。
  • 扫描字符串参数,它会跳过前面的空白字符(如空格、制表符、换行符等)如果遇到非数字字符,解析过程会停止。

函数的原型

代码语言:javascript
复制
int atoi(const char *str);
  • str:指向要转换的字符串的指针。
    • 如果字符串的第一个非空白字符是有效的数字字符(包括正负号)->atoi函数会跳过前面的空白字符(如空格、制表符、换行符等)
      • 例如:对于字符串"123abc"atoi函数会将"123"部分转换为整数,而忽略"abc"部分。
    • 如果字符串的第一个非空白字符不是有效的数字字符->atoi函数返回 0
      • 例如:对于字符串"abc"atoi会返回 0。
    • 如果字符串为空串->atoi函数返回 0
      • 例如:对于字符串""atoi会返回 0。
    • 如果字符串以'-'开头**->转换后的整数为负数;如果以'+'开头->**转换后的整数为正数。

to_string函数

函数的介绍 to_string :用于将数值类型(如整数、浮点数等)转换为string类型。

  • 它定义在头文件 <string> 中。
  • 这在需要将数字和字符串拼接、或者将数字以字符串形式存储或输出等场景中非常有用。

to_string 函数可以处理以下几种常见的数据类型:

  1. 整数类型(如 int, long, long long, unsigned int, unsigned long, unsigned long long 等)。
  2. 浮点数类型(如 float, double, long double)。

函数的原型

函数原型根据不同的参数类型有所不同:

对于整数类型:

代码语言:javascript
复制
string to_string(int val);

对于长整数类型:

代码语言:javascript
复制
string to_string(long val);

对于无符号整数类型:

代码语言:javascript
复制
string to_string(unsigned int val);

函数的使用

这里简单列举几个to_string函数的使用的实例:

整数类型(int

代码语言:javascript
复制
int num = 123; 
string str = to_string(num);
  • 解释:这里将整数123转换为字符串形式,转换后的str内容为"123"

无符号整数类型(unsigned int

代码语言:javascript
复制
unsigned int unum = 456; 
string ustr = to_string(unum);
  • 将无符号整数456转换为字符串,转换后的ustr的内容为"456"

长整数类型(long)和无符号长整数类型(unsigned long

代码语言:javascript
复制
long lnum = 789L; 
std::string lstr = to_string(lnum);

unsigned long ulnum = 1011UL; 
string ulstr = to_string(ulnum);
  • 分别将长整数789L和无符号长整数1011UL转换为字符串,
  • 转换后的lstr的内容为"789"ulstr的内容为"1011"

浮点数类型(floatdouble

代码语言:javascript
复制
float fnum = 3.14f; 
string fstr = to_string(fnum);
   
double dnum = 2.71828; 
string dstr = to_string(dnum);
  • 将浮点数3.14f2.71828转换为字符串,
  • 转换后的fstr的内容可能是"3.140000"(具体的小数位数可能因编译器和系统设置等因素而有所不同)
  • 转换后的dstr的内容也类似,如"2.718280"

其他:

在进行数字和字符串拼接操作时,to_string函数提供了便捷的方式。

代码语言:javascript
复制
//可以将多个数字和字符串拼接在一起
string result = "The number is " + to_string(7) + " and the float is " + to_string(3.14);

方法三:

代码展示

代码语言:javascript
复制
#include<iostream>
#include<cstdio>  //使用sscanf 和 sprintf 和 fgets
#include<cstring> //使用memset 和 strlen 
using namespace std;

int main() 
{
	int x[100] = { 0 }, y[100] = { 0 };
	char operatorChar[100] = { 0 };
	char input[100], resultString[100];

	int n;
	cin >> n;
	getchar();
	for (int i = 0; i < n; i++) 
	{
		memset(input, 0, sizeof(input));
		fgets(input, sizeof(input), stdin);
        
		// 去除换行符(因为 fgets 会把换行符也读进来,可能不符合后续处理逻辑需求)
		size_t len = strlen(input);
		if (len > 0 && input[len - 1] == '\n')
		{
			input[len - 1] = '\0';
		}

		//如果输入的第一个是字符,即运算符
		if (input[0] >= 'a' && input[0] <= 'c')
		{
			operatorChar[i] = input[0];
			sscanf(input, "%*s %d %d", &x[i], &y[i]);
		}
		//如果输入的第一个是数字,即操作数
		else 
		{
			operatorChar[i] = operatorChar[i - 1];
			sscanf(input, "%d %d", &x[i], &y[i]);
		}
	}

	for (int i = 0; i < n; i++) 
	{
		memset(resultString, 0, sizeof(resultString));
		if (operatorChar[i] == 'a')
		{
			sprintf(resultString, "%d+%d=%d", x[i], y[i], x[i] + y[i]);
			cout << resultString << endl << strlen(resultString) << endl;
		}
		if (operatorChar[i] == 'b')
		{
			sprintf(resultString, "%d-%d=%d", x[i], y[i], x[i] - y[i]);
			cout << resultString << endl << strlen(resultString) << endl;
		}
		if (operatorChar[i] == 'c')
		{
			sprintf(resultString, "%d*%d=%d", x[i], y[i], x[i] * y[i]);
			cout << resultString << endl << strlen(resultString) << endl;
		}
	}
	return 0;
}

交互过程: 4 a 1 2 3 4 b 5 6 c 7 8 1+2=3 5 3+4=7 5 5-6=-1 6 7*8=56 6

核心模块

为字符数组赋值
代码语言:javascript
复制
fgets(input, sizeof(input), stdin);

// 去除换行符(因为 fgets 会把换行符也读进来,可能不符合后续处理逻辑需求)
size_t len = strlen(input);
if (len > 0 && input[len - 1] == '\n')
{
    input[len - 1] = '\0';
}
根据输入值的类型选择将其存入不同的变量中
代码语言:javascript
复制
//如果输入的第一个是字符,即运算符
if (input[0] >= 'a' && input[0] <= 'c')
{
	operatorChar[i] = input[0];
	sscanf(input, "%*s %d %d", &x[i], &y[i]);
}
//如果输入的第一个是数字,即操作数
else
{
	operatorChar[i] = operatorChar[i - 1];
	sscanf(input, "%d %d", &x[i], &y[i]);
}

语法讲解

fgets函数

函数的介绍: fgets:用于从指定的输入流(通常是文件或标准输入)读取一行字符串,并将它们存储到字符数组中。

  • 直到读取了n - 1个字符、遇到换行符\n或者到达文件末尾(EOF)为止。
  • 它定义在 <cstdio> 头文件中。

函数的原型:

代码语言:javascript
复制
char* fgets(char* str, int n, FILE* stream);
  • str:是一个指向字符数组的指针。
    • 用于存储从输入流中读取的字符串。
  • n:是要读取的最大字符数。
    • 包括最后的字符串结束符\0,因此实际能够存储的最大字符数为 n-1
  • stream:是一个指向 FILE 对象的指针,表示输入流。
    • 用于指定从哪个文件流中读取数据。
    • 最常见的是使用stdin(标准输入)来从键盘读取数据,也可以是通过fopen函数打开的文件流。

函数的使用:

从标准输入读取一行字符串:

代码语言:javascript
复制
#include <cstdio>
#define MAX_LENGTH 100
int main() 
{
    char buffer[MAX_LENGTH];
    
    // 从标准输入读取一行字符串
    fgets(buffer, MAX_LENGTH, stdin);
    printf("你输入的是:%s", buffer);
    
    return 0;
}

从文件读取一行字符串:

代码语言:javascript
复制
#include <cstdio>
#define MAX_LENGTH 100
int main()
{
    char buffer[MAX_LENGTH];
    
    FILE* fp = fopen("test.txt", "r");
    if (fp == NULL)
    {
        perror("打开文件失败");
        return 1;
    }
    
    // 从文件读取一行数据
    fgets(buffer, MAX_LENGTH, fp);
    printf("从文件读取的是:%s", buffer);
    
    fclose(fp);
    return 0;
}

这段代码首先尝试打开一个名为test.txt的文件(以只读方式r

  • 如果打开失败,使用perror函数输出错误信息并返回错误码。
  • 如果打开成功,使用fgets函数从文件中读取一行数据(最多读取MAX_LENGTH - 1个字符),然后输出读取到的内容。
  • 最后关闭文件。

函数的返回值:

  • 如果成功读取fgets函数返回str,也就是指向存储读取内容的字符数组的指针。
  • 如果遇到文件末尾(EOF)且没有读取到任何字符,返回NULL
  • 如果读取过程中遇到错误,但是已经读取了一些字符fgets也会返回str,不过存储在str中的内容可能不完整。
片段一:
代码语言:javascript
复制
sscanf(input, "%*s %d %d", &x[i], &y[i]);

  • %*s:这是一个格式说明符,其中 %s 表示匹配一个字符串。
  • 但是前面的 * 起到了抑制赋值的作用,意思是按照字符串格式匹配相应内容,但不把匹配到>的内容赋值给任何变量。
  • 也就是跳过(忽略)字符串最开始的那部分内容(刚好是之前已经提取出来当作操作符的那个>字符)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 洛谷题单:【入门5】字符串->"P1957 口算练习题"(多法实现+语法讲解)
  • 题目介绍
  • 方法一:
    • 代码展示
    • 核心模块
      • 根据输入值的类型选择将其存入不同的变量中
      • 将一些基本数据类型的变量合并成字符串
    • 语法讲解
      • sscanf函数
      • sprintf函数
      • memset函数
  • 方法二:
    • 代码展示
    • 核心模块
      • 根据输入值的类型选择将其存入不同的变量中
      • 将一些基本数据类型的变量合并成字符串
    • 语法讲解
      • atoi函数
      • to_string函数
  • 方法三:
    • 代码展示
    • 核心模块
      • 为字符数组赋值
      • 根据输入值的类型选择将其存入不同的变量中
    • 语法讲解
      • fgets函数
      • 片段一:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档