这为什么会这么分裂?函数strtok?

时间:2014-10-06 15:16:02

标签: c segmentation-fault strtok

所以我很好奇为什么以下代码段保持segfaulting。它对我来说是正确的。

int * addCoins(char *val){
    const char *deli = ",";
    char *ptr =NULL;

    char *denomination = strtok_r(val, deli, &ptr);
    char *count = strtok_r(NULL, deli, &ptr);
    int deno = atoi(denomination);
    int cnt = atoi(count);
    int *k;
    k = malloc(sizeof(*k)*2);
    k[0] = deno;
    k[1] =cnt;

    return k;
}

在main中调用函数addCoins。我不认为错误在于此,但老实说我对这个问题有点失落。

char* fileNameCoin = argv[2];
FILE *fileCoin;
fileCoin = fopen(fileNameCoin, "r+");
char bufCoin[256];
int i = 0;
//vmNode->next = NULL;
int *j;
while (fgets(bufCoin, sizeof bufCoin, fileCoin) != NULL) {
    j = addCoins(bufCoin);
    int deno = j[0];
    switch(deno){
        case 5:
            Coins[i].denom = j[0];
            Coins[i].count = j[1];
            break;
        case 10:
            Coins[i].denom = j[0];
            Coins[i].count = j[1];
            break;
        case 20:
            Coins[i].denom = j[0];
            Coins[i].count = j[1];
            break;
        case 50:
            Coins[i].denom = j[0];
            Coins[i].count = j[1];
            break;
        case 100:
            Coins[i].denom = j[0];
            Coins[i].count = j[1];
            break;
        case 200:
            Coins[i].denom = j[0];
            Coins[i].count = j[1];
            break;
        case 500:
            Coins[i].denom = j[0];
            Coins[i].count = j[1];
            break;
        case 1000:
            Coins[i].denom = j[0];
            Coins[i].count = j[1];
            break;
        default:
            break;
    }

    i++;
}

以下是文件的定义方式

1000,3
500,4
200,20
100,30
50,5
20,3
10,40
5,20

其中第一个数字是以美分为单位的面额,第二列是所述面额的数量。

这些是typedef:

/* The different denominations of coins available */
enum denomination
{
    FIVE_CENTS, TEN_CENTS, TWENTY_CENTS, FIFTY_CENTS, ONE_DOLLAR,
    TWO_DOLLARS, FIVE_DOLLARS, TEN_DOLLARS
};

/* Each coin in the coins array will have a denomination (20 cents,
 * 50 cents, etc) and a count - how many of that coin do we have on hand
 */
struct coin
{
    enum denomination denom;
    unsigned count;
};

2 个答案:

答案 0 :(得分:1)

老实说,您应该通过structs更好地使用typedef。示例(使用exename in.txt调用):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* The different denominations of coins available */
enum denomination {
    FIVE_CENTS, TEN_CENTS, TWENTY_CENTS, FIFTY_CENTS, ONE_DOLLAR,
    TWO_DOLLARS, FIVE_DOLLARS, TEN_DOLLARS
};

typedef struct {
    enum denomination denom;
    unsigned int count;
} coin;

coin * addCoins(char *val) {
    coin *k = malloc(sizeof(coin));
    if( sscanf( val, "%d,%d", &(k->denom), &(k->count)) != 2 ) {
      fprintf(stderr,"Two int values not found on line '%s' in input.\n", val);
      free(k);
      k=NULL;
    }
    return k;
} 

int main(int argc, char *argv[])
{
    coin Coins[100]={0};
    char* fileNameCoin = argv[1];
    FILE *fileCoin = fopen(fileNameCoin, "r+");
    char bufCoin[256];
    int i = 0;
    coin *j;
    if( fileCoin ) {
      while(fgets(bufCoin, sizeof bufCoin, fileCoin) != NULL) {
        j = addCoins(bufCoin);                                                                                       
        if( j ) { // only add if 2 int values found on input line
          Coins[i] = *j;
          free(j);
          printf("c: %d, %d\n", Coins[i].denom, Coins[i].count);
          i++;
        } 
      }
      fclose(fileCoin);
    }
    else {
      fprintf(stderr,"Unable to open file %s for input.\n",fileNameCoin);
    }
}

答案 1 :(得分:0)

您已经对代码进行了更彻底的重新实现,这实际上非常好。这是一套应用于原始代码的清理工作;它表明程序中出现的任何问题都不在显示的代码中。

#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum denomination
{
    FIVE_CENTS, TEN_CENTS, TWENTY_CENTS, FIFTY_CENTS, ONE_DOLLAR,
    TWO_DOLLARS, FIVE_DOLLARS, TEN_DOLLARS
};

struct coin
{
    enum denomination denom;
    unsigned count;
};

static struct coin Coins[10];

static
int *addCoins(char *val)
{
    const char *deli = ",";
    char *ptr = NULL;

    char *denomination = strtok_r(val, deli, &ptr);
    char *count = strtok_r(NULL, deli, &ptr);
    printf("D = %s, C = %s", denomination, count);
    int deno = atoi(denomination);
    int cnt = atoi(count);
    printf("D = %d, C = %d\n", deno, cnt);
    int *k = malloc(sizeof(*k) * 2);
    if (k == 0)
    {
        fprintf(stderr, "Failed to allocate memory\n");
        exit(1);
    }
    k[0] = deno;
    k[1] = cnt;

    return k;
}

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s file\n", argv[0]);
        return 0;
    }
    char *fileNameCoin = argv[1];
    FILE *fileCoin = fopen(fileNameCoin, "r+");
    if (fileCoin == 0)
    {
        fprintf(stderr, "%s: failed to open file %s\n", argv[0], argv[1]);
        return 0;
    }
    char bufCoin[256];
    int i = 0;
    while (fgets(bufCoin, sizeof bufCoin, fileCoin) != NULL)
    {
        int *j = addCoins(bufCoin);
        int deno = j[0];
        switch (deno)
        {
        case 5:
        case 10:
        case 20:
        case 50:
        case 100:
        case 200:
        case 500:
        case 1000:
            Coins[i].denom = j[0];
            Coins[i].count = j[1];
            printf("(%d,%d)\n", Coins[i].denom, Coins[i].count);
            i++;
            break;
        default:
            fprintf(stderr, "Unrecognized coin denomination (%d,%d)\n", j[0], j[1]);
            break;
        }
        free(j);
    }
    return 0;
}

汇编:

gcc -g -O3 -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -Wold-style-declaration -Werror coins.c -o coins

#define _XOPEN_SOURCE 700是宣传strtok_r()所必需的。

示例运行:

D = 1000, C = 3
D = 1000, C = 3
(1000,3)
D = 500, C = 4
D = 500, C = 4
(500,4)
D = 200, C = 20
D = 200, C = 20
(200,20)
D = 100, C = 30
D = 100, C = 30
(100,30)
D = 50, C = 5
D = 50, C = 5
(50,5)
D = 20, C = 3
D = 20, C = 3
(20,3)
D = 10, C = 40
D = 10, C = 40
(10,40)
D = 5, C = 20
D = 5, C = 20
(5,20)