多次运行函数时的不同结果-C
我已经编写了一个函数,当我运行它时,一旦它工作正常,但当我使用不同的输入运行它多次时,就会出现问题多次运行函数时的不同结果-C,c,function,memory-leaks,C,Function,Memory Leaks,我已经编写了一个函数,当我运行它时,一旦它工作正常,但当我使用不同的输入运行它多次时,就会出现问题 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> #define MAX_SIZE 20 int SumStr(char *str) { int i = 0, j = 0, num = 0, tempnum = 0; char tem
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define MAX_SIZE 20
int SumStr(char *str) {
int i = 0, j = 0, num = 0, tempnum = 0;
char temp[MAX_SIZE];
while (*(str + i) != 0) { //While not NULL - Checked
while (((*(str + i)) >= 48) && ((*(str + i)) <= 57)) { //while str[i] is [0-9]
*(temp + j) = *(str + i);
++j; ++i;
}
if (j != 0) {
tempnum = atoi(temp);
num = tempnum + num;
tempnum = 0;
j = 0;
}
++i;
}
return num;
}
void Test3(char *arr, int sum)
{
int tempSum = SumStr(arr);
if (tempSum != sum)
{
printf("Your Output is %d, Expected: %d (-3)\n", tempSum, sum);
}
}
void main() {
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
}
但是当main使用不同的输入多次运行函数时,输出是完全错误的
这条主线的输出
void main() {
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
}
是
一个问题是,在将
temp
-字符串传递给atoi
之前,您没有使用'\0'
-字符终止该字符串。
你可以写:
temp[j] = '\0'; // or: *(temp + j) = '\0';
if (j != 0) { ...
请注意,将未正确以'\0'
结尾的字符序列传递给期望(终止)字符串的函数会产生未定义的行为;那可能就是你当时观察到的
第二,如果输入字符串的最后一个字符是数字,则将i
增加两次,从而错过输入的字符串终止字符。这再次导致未定义的行为。要克服这个问题,可以在递增i
之前检查是否在字符串末尾:
if (*(str + i) != 0) {
++i;
}
除了不终止
temp[j]
,还可以通过在内环和外环中递增i
跳过str
中的终止字符。
当您跳过终止时,它开始处理下一个字符串[或者根据您的编译器/操作系统,处理任何旧的垃圾]
顺便说一句,
while(isdigit(str[i])
不仅比您的可读性、可移植性和效率更高,而且使注释变得不必要。正确运行程序:
//Explanations in the commemnts
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define MAX_SIZE 20
int SumStr(char *str) {
int i = 0, j = 0, num = 0, tempnum = 0;
char temp[MAX_SIZE];
while (*(str + i) != 0) {
//While not NULL - Checked
while ( (( *(str + i)) >= '0') && ((*(str + i)) <= '9') ) // more readable
{ //while str[i] is [0-9]
*(temp + j) = *(str + i);
++j;
++i;
}
if (j != 0) {
*(temp + j) = 0; // termination of the string needed for atoi
tempnum = atoi(temp);
num = tempnum + num;
tempnum = 0;
j = 0;
}
// new:
if (*(str + i) != 0) {
++i;
}
else break; // detection of the end of string
}
return num;
}
void Test3(const char *arr, int sum)
{
int tempSum = SumStr(arr);
if (tempSum != sum)
{
printf("Your Output is %d, Expected: %d (-3)\n", tempSum, sum);
}
}
void main() {
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
return 0;
}
//社区中的解释
#包括
#包括
#包括
#包括
#定义最大尺寸20
int SumStr(字符*str){
int i=0,j=0,num=0,tempnum=0;
字符温度[最大大小];
而(*(str+i)!=0){
//而不是空-检查
虽然((*(str+i))>='0')&(*(str+i))我想祝贺您使用了问题中显示的测试代码。也就是说,IMO是一种出色的工作方式
此代码不尝试修复原始代码(已由完成)。此代码显示了处理此问题的完全不同的方法。它使用不同的库函数集-和-并且避免了对源字符串的任何复制(因此不会遇到空终止字符串的问题)
(是的:当我在代码中有一个bug时,我确实得到了!!失败!!
行。)除非你的任务是尽可能地编写最模糊的代码,(*(str+I))>=48&(*(str+I))='0'&&s[I],或者使用isdigit()
来自
。事实上,我正在测试指针的使用,这就是为什么这段代码是这样写的。此外,我不能使用ctype.h,我只能使用我在代码中已经提到的库。谢谢!不,这项任务不会强迫你写这种讨厌的东西。你可以随时添加一个临时字符c=*(str+i)
。无论您的任务标准如何,与幻数的比较都是不可原谅的。@StoryTeller我完全同意这段代码很糟糕。谢谢您的评论!是的,这是个问题,但大多数情况下对atoi
来说都无关紧要。通过此修复,我仍然有3次未命中。在将其传递给atoi之前,我尝试将temp设为NULL,但仍然没有成功ll将有3次未命中。@LiorgingHashvili正确终止修复此问题的相关性讨论起来有些毫无意义。如果不这样做是完全错误的,如果在调用任何函数(标准库或其他)之前未终止该字符串,则会调用未定义的行为。即使它没有“修复”这个问题,它本身应该是固定的,因为它(a)消除了未定义的行为,(b)减少了导致你的问题的可能性。@Jean-François Fabre:对;两者都会导致UB,所以我只是删除了“main”这确实帮助我理解并解决了这个问题,非常感谢。也感谢大家的建议!isdigit
确实更具可读性;它也是在ctype.h
中定义的,OP表示他们不能使用它。我注意到,对于空字符串,代码安全地生成零-第一个字节是空字节的一种。
if (*(str + i) != 0) {
++i;
}
//Explanations in the commemnts
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define MAX_SIZE 20
int SumStr(char *str) {
int i = 0, j = 0, num = 0, tempnum = 0;
char temp[MAX_SIZE];
while (*(str + i) != 0) {
//While not NULL - Checked
while ( (( *(str + i)) >= '0') && ((*(str + i)) <= '9') ) // more readable
{ //while str[i] is [0-9]
*(temp + j) = *(str + i);
++j;
++i;
}
if (j != 0) {
*(temp + j) = 0; // termination of the string needed for atoi
tempnum = atoi(temp);
num = tempnum + num;
tempnum = 0;
j = 0;
}
// new:
if (*(str + i) != 0) {
++i;
}
else break; // detection of the end of string
}
return num;
}
void Test3(const char *arr, int sum)
{
int tempSum = SumStr(arr);
if (tempSum != sum)
{
printf("Your Output is %d, Expected: %d (-3)\n", tempSum, sum);
}
}
void main() {
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static
int SumStr(const char *str)
{
int sum = 0;
str += strcspn(str, "0123456789");
while (*str >= '0' && *str <= '9')
{
/*
** Since *str is a digit, the value will not be negative and
** strtol() won't fail unless the value is too big for a long.
** Since we can't include <limits.h> (or <assert.h>, or
** <errno.h>), I plan to ignore overflow.
*/
char *eon;
long val = strtol(str, &eon, 10);
sum += (int)val;
str = eon + strcspn(eon, "0123456789");
}
return sum;
}
static
void Test3(char *arr, int sum)
{
int tempSum = SumStr(arr);
const char *pass_fail = (tempSum == sum) ? "**PASS**" : "!!FAIL!!";
printf("%s Output: %5d, Expected: %5d, Data (%s)\n",
pass_fail, tempSum, sum, arr);
}
int main(void)
{
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
Test3("x$.!-_+", 0);
Test3("xxx1000y2345z3456=23412!", 30213);
Test3("-0+0-0+0-", 0);
return 0;
}
**PASS** Output: 19, Expected: 19, Data (ax3b5mt11f)
**PASS** Output: 15, Expected: 15, Data (5$5$5)
**PASS** Output: 1234, Expected: 1234, Data (1234)
**PASS** Output: 101, Expected: 101, Data (1$0!100)
**PASS** Output: 3, Expected: 3, Data (1$1!1)
**PASS** Output: 0, Expected: 0, Data (x$.!-_+)
**PASS** Output: 30213, Expected: 30213, Data (xxx1000y2345z3456=23412!)
**PASS** Output: 0, Expected: 0, Data (-0+0-0+0-)