多次运行该函数时的结果不同 - C.

时间:2017-12-16 20:53:46

标签: 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 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);
}

该函数的目的是对字符串中的所有数字求和。

当我使用此主程序运行该功能一次时(例如),它可以正常工作;

void main() {
Test3("1$0!100", 101);
}

Output: num=101

但是当main使用不同的输入多次运行该函数时,输出完全错误。

此主要的输出;

void main() {
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
}

时;

Your Output is 6871, Expected: 15
Your Output is 6718, Expected: 1234
Your Output is 5024, Expected: 101

4 个答案:

答案 0 :(得分:5)

一个问题是,在将temp - 字符串传递给'\0'之前,您不会终止atoi字符串。 你可以写:

temp[j] = '\0';  // or: *(temp + j) = '\0';
if (j != 0) { ...

请注意,将未使用'\0'正确终止的字符序列传递给期望(终止)字符串的函数会产生未定义的行为;这可能是你当时观察到的。

其次,如果输入字符串的最后一个字符是数字,则增加i两次,从而错过输入的字符串终止字符。这再次导致未定义的行为。要解决此问题,您可以在递增i之前检查是否位于字符串的末尾:

    if (*(str + i) != 0) {
      ++i;
    }

答案 1 :(得分:3)

除了不终止temp[j]之外,还可以通过在内循环和外循环中递增str来跳过i中的终止字符。 当你跳过终止时,它开始处理下一个字符串[或取决于你的编译器/操作系统,任何旧的垃圾]。

btw,while (isdigit(str[i]))不仅比你的更具可读性,便携性和高效性,而且还不需要注释。

答案 2 :(得分:1)

我想祝贺Lior Gingihashvili使用问题中显示的测试代码。也就是说,IMO是一种很好的工作方式。

此代码不会尝试修复原始代码 - 这已由accepted answer完成。此代码显示了一种完全不同的方法来解决问题。它使用一组不同的库函数 - strcspn()strtol() - 它避免了对源字符串的任何复制(因此它不会遇到null终止字符串的问题)。

#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-)

(是的:当我在代码中出现错误时,我确实获得了!!FAIL!!行。)

答案 3 :(得分:0)

正确运行程序:

//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;
}