【问题标题】:using atoi() not printing desired output使用 atoi() 不打印所需的输出
【发布时间】:2015-02-22 15:02:01
【问题描述】:

我的文本文件是 IP_CONFIG.txt

"192.168.128.3" IP_CS 
"192.168.128.2" IP_HM 
"192.168.128.1" IP_OB 
"192.168.128.4" IP_AS 
"127.0.0.1" IP_RS 
"127.0.0.1" IP_RS_D 
"1901" PORT_CS 
"1901" PORT_HM
"1901" PORT_OB
"3567" PORT_AS
"4444" PORT_RS
"7777" PORT_RS_D

我的代码是

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXWORDS 30

int main(){
    FILE *fp;
    int i=0, j;
    char *words=NULL,*word=NULL,c;
    char *allwords[MAXWORDS];

    if ((fp=fopen("IP_CONFIG.txt","r"))==NULL){ 
        printf("Error Opening File\n");
        exit(1);}
    while ((c = fgetc(fp))!= EOF){
        if (c=='\n'){ c = ' '; }
        words = (char *)realloc(words, ++i*sizeof(char));
        words[i-1]=c;}
    word=strtok(words," ");
    i=0;
    while(word!= NULL && i < MAXWORDS){
        //printf("%s\n",word);
        allwords[i] = malloc(strlen(word));
        strcpy(allwords[i], word);
        word = strtok(NULL," ");
        i++;        
    }
    printf("\nNow printing each saved string:\n");
    for (j=0; j<i; j++){
        printf("String %d: %s\n", j, allwords[j]);
        }
   char * IP_CS   = allwords[0];    
   char *IP_HM   = allwords[2];   
   char *IP_OB  = allwords[4];      
   char *IP_AS   = allwords[6];      
   char *IP_RS   = allwords[8];      
   char *IP_RS_D = allwords[10]; 

   int PORT_CS   = atoi(allwords[12]);
   int PORT_HM   = atoi(allwords[14]); 
   int PORT_OB   = atoi(allwords[16]);
   int PORT_AS   = atoi(allwords[18]);
   int PORT_RS   = atoi(allwords[20]);
   int PORT_RS_D = atoi(allwords[22]);




   printf("The IPs are \n %s\n %s\n %s\n %s\n %s\n %s\n",IP_CS,IP_HM,IP_OB,IP_AS,IP_RS,IP_RS_D);
   printf("The PORTSs are \n %d\n %d\n %d\n %d\n %d\n %d\n",PORT_CS,PORT_HM,PORT_OB,PORT_AS,PORT_RS,PORT_RS_D);    

    exit(0);
}

我已经解决了正确获取 IP 地址的问题,但我无法解决端口问题。因为它应该是在我的其他程序中使用的整数值,因此我使用了 atoi。但为什么我的输出只有零......而不是1901,3567等......(下面是输出)

Now printing each saved string:
String 0: "192.168.128.3"
String 1: IP_CS
String 2: "192.168.128.2"
String 3: IP_HM
String 4: "192.168.128.1"
String 5: IP_OB
String 6: "192.168.128.4"
String 7: IP_AS
String 8: "127.0.0.1"
String 9: IP_RS
String 10: "127.0.0.1"
String 11: IP_RS_D
String 12: "1901"
String 13: PORT_CS
String 14: "1901"
String 15: PORT_HM
String 16: "1901"
String 17: PORT_OB
String 18: "3567"
String 19: PORT_AS
String 20: "4444"
String 21: PORT_RS
String 22: "7777"
String 23: PORT_RS_D
The IPs are 
 "192.168.128.3"
 "192.168.128.2"
 "192.168.128.1"
 "192.168.128.4"
 "127.0.0.1"
 "127.0.0.1"
The PORTSs are 
 0
 0
 0
 0
 0
 0

如何获得文本文件中描述的确切端口号。谢谢

【问题讨论】:

  • 编写一个测试程序来了解atoi() 的工作原理,哪个输入需要,哪个不需要。
  • 我强烈建议使用strtol 而不是atoiatoi 有几个明显的缺陷,其中最重要的是,如果它解析一个大于 INT_MAX 的数字,它会导致未定义的行为。

标签: c file port


【解决方案1】:
  1. 您的字符串周围有",这导致转换失败。
  2. 您不会 '\0' 终止 words 缓冲区,因此将其传递给 strtok() 会导致未定义的行为。

  3. 你的问题很严重

    allwords[i] = malloc(strlen(word));
    

    应该是

    allwords[i] = malloc(1 + strlen(word));
    

    因为您需要考虑终止'\0' 字节。

我已经修复了你的程序,在这里

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXWORDS 30

int main()
{
    FILE *fp;
    int   i = 0, j;
    char *words = NULL, *word = NULL, c;
    char *allwords[MAXWORDS] = {NULL};

    if ((fp=fopen("IP_CONFIG.txt","r"))==NULL)
    {
        printf("Error Opening File\n");
        return 1;
    }
    while ((c = fgetc(fp)) != EOF)
    {
        void *pointer;
        if (c=='\n')
            c = ' ';
        pointer = realloc(words, (i + 1) + 1);
        if (pointer == NULL)
        {
            free(words);
            return 2;
        }
        words    = pointer;
        words[i++] = c;
    }
    words[i] = '\0';

    word = strtok(words, " ");
    i    = 0;
    while ((word != NULL) && (i < MAXWORDS))
    {
        const char  *pointer;
        size_t       length;

        pointer = word;
        while ((isspace(pointer[0]) != 0) || (pointer[0] == '"'))
            pointer++;
        length = strlen(pointer);
        while ((isspace(pointer[length - 1]) != 0) || (pointer[length - 1] == '"'))
            length--;
        allwords[i] = malloc(1 + length);
        if (allwords[i] != NULL)
        {
            allwords[i][length] = '\0';
            memcpy(allwords[i], pointer, length);
        }
        word = strtok(NULL, " ");

        i++;
    }
    printf("\nNow printing each saved string:\n");
    for (j = 0 ; j < i ; j++)
        printf("String %d: %s\n", j, allwords[j]);

    enum Ids
    {
        CS, HM, OB, AS, RS, RS_D, EnumSize
    };
    enum Ids ids;
    char *names[] = {"CS", "HM", "OB", "AS", "RS", "RS_D"};

    for (ids = CS ; ((ids < i) && (ids < EnumSize)) ; ids++)
    {
        char       *endptr;
        const char *ip;
        int         port;

        ip = allwords[2 * ids];
        if (allwords[12 + 2 * ids] != NULL)
        {
            port = strtol(allwords[12 + 2 * ids], &endptr, 10);
            if (*endptr != '\0')
                printf("error, invalid port value %s\n", allwords[12 + 2 * ids]);
        }
        else if (ip != NULL)
            printf("%-4s:\n\tip  : %s\n\tport: %d\n", names[ids], ip, port);
    }
    return 0;
}

【讨论】:

  • strtok 容易出错且不可重入。使用strchr 可以轻松重写代码。在将 allwords[12 + 2 * ids] != NULL 传递给 strtol 后测试它,并可能导致未定义的行为。您测试了 mallocrealloc 失败但未能正确报告它,要么在没有消息的情况下退出,要么只是忽略它。
  • 您可以使用错误代码创建enum 例如,注意每个错误处理程序块返回不同的值,重点是检查而不是忽略可能的失败,strtok() 不是太邪恶了,我不想向 OP 展示我知道的更好的技术来实现这一点,而是如何修复代码。
  • @iharob 如果我稍后必须在我的代码中使用 AS 的 IP 和 AS 的端口,我将如何使用,因为您没有使用端口作为指针数组。例如,我如何在这里调用值(IP_AS 和 PORT_AS) italic bold bzero(&amp;(ASR_addr.sin_zero),sizeof(ASR_addr)); ASR_addr.sin_family = AF_INET; ASR_addr.sin_port = htons(PORT_AS); ASR_addr.sin_addr.s_addr = inet_addr(IP_AS);
  • @ZZ2014 您可以将enum 移动到全局范围,并使用适当的enum 值访问数组。请注意,这需要正确排序文件。
  • 我不想要这种方式,因为以下操作仅以这种方式执行bzero(&amp;(ASR_addr.sin_zero),sizeof(ASR_addr)); ASR_addr.sin_family = AF_INET; ASR_addr.sin_port = htons(1902); ASR_addr.sin_addr.s_addr = inet_addr("192.168.2.3"); 所以我的目标是获取带有“”的 IP 和端口作为整数值,以便稍后使用它.你能推荐一下吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多