多次运行函数时的不同结果-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-)