【问题标题】:Parsing a string seems to produce random characters解析字符串似乎会产生随机字符
【发布时间】:2022-06-10 19:48:36
【问题描述】:

我尝试制作一个文件解析器,但是当我尝试将一些值转换为浮点数时,我得到的输出几乎看起来像随机数。这是一些应该显示的输出:

rado@admin fileloader $ ./a.out 
0.000000
rado@admin fileloader $ ./a.out 
-1660525314832519397376.000000
rado@admin fileloader $ ./a.out 
16667839226490398646992896.000000
rado@admin fileloader $ ./a.out 
-3305570304000.000000 

这是我要解析的字符串:

1.000000 1.000000 -1.000000
1.000000 -1.000000 -1.000000
1.000000 1.000000 1.000000
1.000000 -1.000000 1.000000
-1.000000 1.000000 -1.000000
-1.000000 -1.000000 -1.000000
-1.000000 1.000000 1.000000
-1.000000 -1.000000 1.000000

这是代码:

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

int main(){
   char output[1000];
   char buffer;
   char string[2] = {' ', '\0'};
   int i = 0;
   int f = 0;
   char output1[50] = {'\0'};
   float output2[50];
   if(load_obj("model.obj", output, 'v') == 1){
      return 1;
   }
   while(buffer != '\0'){
      buffer = output[i];
      string[0] = buffer;
      if(buffer != ' '){
         strcat(output1, string);
     i++;
      }else{
         output2[f] = strtod(output1, NULL);
     i++;
         f++;
      }
   }
   printf("%s", output1);
   printf("%f\n", output2[2]);
   return 0;
}

load_obj 函数工作正常,因为我得到了正确的输出。似乎代码在strcat(output1, string); 附近失败,因为 output1 为空。这可能是什么原因?

编辑:这是obj.h 头文件:

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

int load_obj(const char* filename, char* output, char type){
   FILE* file = fopen(filename, "r");
   int filepart;
   char string[1000] = {'\0'};
   char tostring[2] = {'\0'};
   if(file == NULL){
      printf("Failed to open file!");
      return 1;
   }
   if(type == 'v'){
      while(filepart != EOF){
         while(filepart != '\n'){
            filepart = fgetc(file);
         }
         filepart = fgetc(file);
         if(filepart == 'v'){
            filepart = fgetc(file);
        if(filepart == ' '){
           while(filepart != '\n'){
              filepart = fgetc(file);
              //printf("%c", filepart);
                  tostring[0] = filepart;
              strcat(string, tostring);
           }
        }
         }
      }
   }
   if(type == 'n'){
      while(filepart != EOF){
         while(filepart != '\n'){
            filepart = fgetc(file);
         }
         filepart = fgetc(file);
         if(filepart == 'v'){
            filepart = fgetc(file);
            if(filepart == 'n'){
           filepart = fgetc(file);
               while(filepart != '\n'){
                  filepart = fgetc(file);
                  //printf("%c", filepart);
                  tostring[0] = filepart;
                  strcat(string, tostring);
               }
            }
         }
      }
   }
   if(type == 't'){
      while(filepart != EOF){
         while(filepart != '\n'){
            filepart = fgetc(file);
         }
         filepart = fgetc(file);
         if(filepart == 'v'){
            filepart = fgetc(file);
            if(filepart == 't'){
           filepart = fgetc(file);
               while(filepart != '\n'){
                  filepart = fgetc(file);
                  //printf("%c", filepart);
                  tostring[0] = filepart;
                  strcat(string, tostring);
               }
            }
         }
      }
   }
   if(type == 'f'){
      while(filepart != EOF){
         while(filepart != '\n'){
            filepart = fgetc(file);
         }
         filepart = fgetc(file);
         if(filepart == 'f'){
            filepart = fgetc(file);
            if(filepart == ' '){
               while(filepart != '\n'){
              filepart = fgetc(file);
                  //printf("%c", filepart);
                  tostring[0] = filepart;
                  strcat(string, tostring);
               }
            }
         }
      }

   }
   fclose(file);
   strcpy(output, string);
   return 0;
}

【问题讨论】:

  • 变量buffer在第一次使用时未初始化。
  • 什么是obj.hload_obj 是什么?调用load_objoutput 中有什么内容?请edit 并提供minimal reproducible example,这意味着您需要做一些工作。
  • @Jabberwocky obj.h 只是我为波前 obj 格式创建的一个简单文件解析器。它从文件中获取所有顶点并将它们作为字符串返回。字符串output 在描述中列出。
  • strtod(output1, NULL); 不是传递NULL,而是传递一个指针的地址。该指针将成为下一次调用strtod 的起点,并将在字符串中循环。
  • @RadoslavL 请发一个minimal reproducible example,我们可以复制/粘贴/运行。$

标签: c string


【解决方案1】:

可以使用一对指针来遍历字符串。
而不是将NULL 传递给strtod,而是传递一个指针的地址。该指针将成为下一次调用 strtod 的字符串的开头。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <math.h>

int main ( void) {
    char output[1000] = "-1.000000 1.000000 -1.000000 3.14159";
    char *iterate = output; //pointer points to start of output
    char *end = NULL;
    double value = 0.0;

    do {
        errno = 0;
        value = strtod ( iterate, &end); //parse from pointer
        if ( ( errno == ERANGE && ( value == HUGE_VAL || value == -HUGE_VAL))
        || ( errno != 0 && value == 0.0)){
            perror ( "problem: ");
            return 1;// failure
        }
        if ( end == iterate) { //nothing parsed
            printf ( "input [%s] MUST be a number\n", iterate);
            return 1;// failure
        }
        printf ( "%f\n", value);
        end += strspn ( end, " \r\n\t"); //advance past space newline tab
                                         //carriage return
        iterate = end; // assign end to iterate. becomes the start for the next call to strtod
    } while ( *end);

    return 0; //success
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    • 2017-08-01
    • 2011-06-30
    相关资源
    最近更新 更多