允许用户在数组函数中更改“5”的值
Posted
技术标签:
【中文标题】允许用户在数组函数中更改“5”的值【英文标题】:Allows the user to change the value of "5" inside array function 【发布时间】:2022-01-03 23:36:13 【问题描述】:正如我的标题所暗示的,我是一个正在玩数组的初学者。尽管我尽力而为,但我无法正确更改数组中的值?如您所见,数组中只有后5位正确,前3位不正确?为什么会这样?我将在下面发布我的代码,以便大家明白我的意思:
#include <stdio.h>
#include <stdlib.h>
#define MAX_ARRAY 8
void input_array(char anumber[MAX_ARRAY])
printf("\n\nPlease insert new data to the 1st array with value 5: ");
fgets(&anumber[0], MAX_ARRAY, stdin);
long ret = strtol(&anumber[0], NULL, 10); // Converts char to int
printf("Converting char anumber = %d to int ret = %d\n", anumber[0], ret);
printf("\n(Array after): ");
for (int i = 0; i < MAX_ARRAY; ++i)
printf("(%d) ", anumber[i]);
int main(void)
char arr[MAX_ARRAY] = 5, 8, 2, 9, 1, 7, 4, 3;
printf("(Array before): ");
for (int i = 0; i < MAX_ARRAY; ++i)
printf("(%d) ", arr[i]);
input_array(arr); // Function that lets the user change value of "5" inside the array
return 0;
如果我作为用户输入值“3”,此代码的输出是:
(Array before): (5) (8) (2) (9) (1) (7) (4) (3)
Please insert new data to the 1st array with value 5: 3
Converting char anumber = 51 to int ret = 3
(Array after): (51) (10) (0) (9) (1) (7) (4) (3)
【问题讨论】:
您试图在同一个变量中包含一个字符串(一个以 null 结尾的字符数组)和一个类型为char
的元素的数值数组。只是不要那样做。使用单独的变量。
旁注:不用写&anumber[0]
,你可以写anumber
。这两个表达式是等价的。
【参考方案1】:
开场白:
线
long ret = strtol(&anumber[0], NULL, 10); // Converts char to int
错了。特别是// Converts char to int
的评论是错误的。函数strtol
不会将单个字符 转换为int
。相反,它会将字符串(即字符序列)转换为long
。
为了将单个数字字符转换为int
,您可以改写以下行:
int number = anumber[0] - '0';
这是可能的,因为 ISO C 要求字符集按顺序存储数字 0
到 9
。
您的程序中实际发生的情况如下:
您正在将数组的 8 个元素初始化为以下值:
(5) (8) (2) (9) (1) (7) (4) (3)
然后,您使用fgets
输入来自用户的字符串"3\n"
。对应的ASCII codes 是数字'3'
的51
和换行符'\n'
的10
。您用这两个值覆盖数组的前两个元素,并用字符串的终止空字符覆盖第三个元素。
这就是为什么数组在调用fgets
后具有以下值的原因:
(51) (10) (0) (9) (1) (7) (4) (3)
fgets
函数会覆盖前 3 个元素,但保留其余元素不变。
解决问题的正确方法如下:
您似乎只想覆盖数组的第一个元素。因此,您不应将数组用作fgets
函数调用的直接目标,因为该函数将始终写入一个以上的字节(正确使用该函数时)。
解决问题的一个非常简单的方法如下:
void overwrite_first_element_with_input( char arr[MAX_ARRAY] )
//prompt user for input
printf( "Please enter new data for the first element of the array: " );
//write input to first element
if ( scanf( "%hhd", &arr[0] ) != 1 )
printf( "input error!\n" );
exit( EXIT_FAILURE );
完整的程序如下所示(有一些小的改进):
#include <stdio.h>
#include <stdlib.h>
#define MAX_ARRAY 8
void overwrite_first_element_with_input( char arr[MAX_ARRAY] )
//prompt user for input
printf( "Please enter new data for the first element of the array: " );
//write input to first element
if ( scanf( "%hhd", &arr[0] ) != 1 )
printf( "input error!\n" );
exit( EXIT_FAILURE );
void print_array( const char arr[MAX_ARRAY], const char *tag )
printf( "%s", tag );
for ( int i = 0; i < MAX_ARRAY; i++ )
printf( "(%d) ", arr[i] );
printf( "\n" );
int main( void )
char arr[MAX_ARRAY] = 5, 8, 2, 9, 1, 7, 4, 3;
print_array( arr, "(Array before): " );
overwrite_first_element_with_input( arr );
print_array( arr, "(Array after): " );
return 0;
这是程序的一些示例输出:
(Array before): (5) (8) (2) (9) (1) (7) (4) (3)
Please enter new data for the first element of the array: 20
(Array after): (20) (8) (2) (9) (1) (7) (4) (3)
但是,我不想鼓励您使用scanf
代替fgets
和strtol
,因为scanf
有many disadvantages。如果你想解决fgets
和strtol
的问题,我推荐以下代码:
void overwrite_first_element_with_input ( char arr[MAX_ARRAY] )
char line[100], *p;
long ret;
//prompt user for input
printf( "Please enter new data for the first element of the array: " );
//attempt to read one line of input and verify success
if (
//verify that fgets was successful
fgets( line, sizeof line, stdin ) == NULL
||
//verify that input buffer was large enough to store entire line
strchr( line, '\n' ) == NULL
)
printf( "input error!\n" );
exit( EXIT_FAILURE );
//attempt to convert input to number
ret = strtol( line, &p, 10 );
if ( p == line )
printf( "conversion failure!\n" );
exit( EXIT_FAILURE );
//write the successfully converted number to the array
arr[0] = ret;
请注意,您必须添加 #include <string.h>
才能使上述代码正常工作。
【讨论】:
哇!这个答案真的值5星!非常感谢您花时间比较 fgets 和 scanf!当一个学徒试图掌握 C 语言的起源时,确实很难……所以再次感谢你! :) @SWEGreven:"Very appreciated when you also took the time to compare both fgets and scanf!"
-- 请不要将scanf
的简单性视为始终使用该功能的鼓励。正如我在回答中已经指出的那样,该功能有很多缺点,可能会导致很多错误。如果您想要一个简单的函数从用户那里读取一个数字,而不必处理输入缓冲区和验证输入,您可能需要编写自己的函数来处理所有这些并基于fgets
。创建这样一个函数可能需要做很多工作,但它会很容易使用。
@SWEGreven:或者你可以使用我的功能get_int_from_user
,我在我的this answer 中发布了该功能。该函数也基于fgets
,并执行广泛的输入验证。使用该功能就像使用scanf
一样简单,但不太容易出现错误。虽然它不如scanf
强大,因为它只能从用户那里获取一个数字。
谢谢老兄!欣赏它:) 只是对这条线感到好奇... char line[100], *p; // 为什么这个值为 100?当我将此值更改为 3 时,它需要 1 位,当 4 时需要 2 位,当 5 时需要 3 位,依此类推...您可以输入到元素的最大数字仅为 127。我们可以以某种方式进一步增加与 fgets?或者这是一个问题,因为 fgets 需要有“char”?
@SWEGreven: char line[100]
-- 通常,在堆栈can be bad 上分配太多内存,因为它可能导致stack overflows(即崩溃)。另一方面,内存缓冲区不应该太小,因为如果用户输入太大而无法放入缓冲区,程序将中止并显示错误消息。因此,大小为 100 字节的缓冲区对我来说似乎是一个合适的折衷方案。但是,如果需要,您可以增加它。【参考方案2】:
你好,我看到你试图将你的数字数组保存在 char 中,所以它可能会导致这种错误。为字符定义两个变量,为数字定义另一个变量。
【讨论】:
正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。以上是关于允许用户在数组函数中更改“5”的值的主要内容,如果未能解决你的问题,请参考以下文章