-1

I'm reading an input file and writing it to a 2D integer array. All the numbers in the file have two characters.

It works good but in all the [48]–[57] elements the integers have a redundant digit (e.g., 30, 871, 447 instead of 3, 87, 44). The same problem with strtol(). The hexadecimal codes of the input file look absolutely normal in those parts.

for (int a = 0; a < d; a++)
{
    for (int b = 0; b < d; b++)
    {
        //read two chars
        uint16_t num;
        fread(&num, sizeof(char) * 2, 1, inptr);

        //convert to int and put to the array (it makes wrong int in 48 <= b <= 57)
        arr[a][b] = atoi((char*)&num);

        //skip space or line break in the input file
        fseek(inptr, sizeof(char), SEEK_CUR);
    }
}

What's the problem? Why do only [48]–[57] work incorrectly?

  • 1
    You should provide a [mre]. In this case you should create a simple main function and remove `fread` and just load `num` with a number that does not work. If you cannot find such a number then you can probably create a [mre] without `atoi` instead. – klutt Oct 24 '19 at 21:56
  • 2
    And besides, `sizeof(char)` is just a fancy way of writing `1` ;) – klutt Oct 24 '19 at 21:56
  • 1
    Also, what is your file encoding? Seem l it seems that you are expecting every number to be separated by**exactly** one character, which might not be the case, especially for new lines – Dr Phil Oct 24 '19 at 22:04
  • 1
    For data such as you describe, your program exhibits undefined behavior as a result of `atoi()` performing an out-of-bounds access, as a result, in turn, of the data you are feeding to it not being null-terminated within the bounds of `num`. Technically, "undefined" means that there's no need to explain why misbehavior occurs for some input data and not for other data, but in practice, I suspect that fixing that problem will not resolve the observed misbehavior. – John Bollinger Oct 24 '19 at 22:06
  • I would give it about 90% certainty that the issue is in the input, not the program, UB notwithstanding. – John Bollinger Oct 24 '19 at 22:08
  • 1
    `atoi` requires a null terminator, but your `fread` does not add a null terminator. It just reads two characters from the file, neither of which is likely to be `\0`. (It's also not clear why you are type-punning into a `uint16_t`. Why not read into an array of characters?) – Raymond Chen Oct 24 '19 at 22:10
  • File is .txt, spaces and new lines are always 1 char, I checked the hexadecimal code of the file. I'll try to change it with and array of characters once again, but last time I had some errors I tried to avoid. – Pavel Egizaryan Oct 24 '19 at 22:35
  • 1
    You *might* be able to get away with something like `char tmp[3]; fread(tmp, 2, 1, inptr); tmp[2] = '\0'; arr[a][b] = atoi(tmp);`. But it looks like `fread` is probably the wrong tool for the job. And `atoi((char*)&num)` is just wrong on the face of it. – Steve Summit Oct 24 '19 at 22:56

1 Answers1

0

Thanks for all the comments, especially for those mentioning the \0 required for atoi.

Using char str[3] instead of uint16_t removes the problem and lets convert all the numbers correctly.

for (int a = 0; a < d; a++)
{
    for (int b = 0; b < d; b++)
    { 
        char str[3];
        str[2] = '\0';
        fread(&str, 2, 1, inptr);
        arr[a][b] = atoi(str);
        fseek(inptr, 1, SEEK_CUR);
    }
}
  • 1
    In addition to `(char*)&num` NOT being a string, `atoi` provides zero error detection and zero way to validate the conversion -- so your invalid use of `atoi` in your original code could not be detected. This is why production code should always use `strtol` or `strtoul` and fully validate (1) that digits were converted, (2) the conversion did not set `errno` and if the resulting type is smaller than the size of the conversion (3) that the value is within range of the final type used. – David C. Rankin Oct 24 '19 at 23:40
  • @DavidC.Rankin All very true, but kinda moot given that he's using `fseek(inptr, 1, SEEK_CUR)` to blindly skip over a character that might be a space, might be a newline, or might accidentally be another digit... – Steve Summit Oct 25 '19 at 00:31
  • Agreed, example input would be very helpful in this case. Though the use of `atoi` versus `strtol`, etc.. would remain the same. – David C. Rankin Oct 25 '19 at 00:34