1

I have a file with numbers on each line. I am trying to write the data read from the file to the int array with the read () function. I can read the file and print it to the terminal. How can i get the numbers i read into arr array ?

Here is my code

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

int main() {
    int len, fd,arr[10000],i=0;
    fd = open("1.txt", O_RDONLY);
    if (fd >= 0) {

        while(read(fd, &len, sizeof(int)) > 0){
            write(1, &len, sizeof(int));

        }
    }

    close(fd);

    return 0;
}
ofbahar
  • 43
  • 4
  • So you mean you want to read text file, in which numbers are expressed in strings? – MikeCAT Nov 27 '20 at 14:32
  • Yes and then I want to write in a array after reading – ofbahar Nov 27 '20 at 14:34
  • `read(fd, arr, len * sizeof *arr)`. Just read directly into the array. No need to read and copy. – William Pursell Nov 27 '20 at 14:41
  • But is `read(fd, &len, sizeof len)` really what you wanted? If this is a text file, that is very likely *not* what you want. – William Pursell Nov 27 '20 at 14:41
  • 1
    You almost certainly want some flavor of `fread/strtol` or `scanf` – William Pursell Nov 27 '20 at 14:42
  • You have to parse the text then and convert it to integers. Look at functions like `strtol()` and `fscanf()`. You can either read it in a string/`char` array and then parse it or create a `FILE *` object and then read it with `fscanf()`. – 12431234123412341234123 Nov 27 '20 at 14:43
  • it's part of my operating systems assignment and i have to use open/read functions – ofbahar Nov 27 '20 at 14:48
  • @ofbahar It works just fine with `read()` when done correctly. But you should only use this functions when you know some basics, like how does the computer store text and how the computer stores `int`'s, before you use functions like `read()`. I think you want to learn the more advanced stuff before you know the basics, this is not a good idea. `read()` has some caveats which you need to take into consideration and i doubt you know enough to account for them, sorry. – 12431234123412341234123 Nov 27 '20 at 15:15
  • @12431234123412341234123 Yes,you are right. I'm trying to learn these – ofbahar Nov 27 '20 at 15:22
  • By the way, you do not use the `arr` nor `i` variables, no reason to create them when you do not need them. – 12431234123412341234123 Nov 27 '20 at 15:49

2 Answers2

1

On most (all?) implementations, a integer stores the binary representation of a number in the bits and bytes of that integer. In the other hand, a string and something like your text file uses bytes to store the ASCII value of digits, spaces and line feeds.

int (assuming 4 byte with 8 bit each, big endian) may store the value 1234 this way:

Address   0x42  0x43  0x44  0x45
Value     0x00  0x00  0x04  0xD2
Text       NUL   NUL   EOT    Ò

In the other hand, a string can contain the ASCII values of each character that represents a text. The String "1234" could be stored like this:

Address   0x82  0x83  0x84  0x85  0x86
Value     0x31  0x32  0x33  0x34  0x00
Text        1     2     3     4    NUL

When you do a read, you read the characters of the text file. Reading them into a char array is easy, you do not need to do any conversation, only add the NUL-Byte at the end. When you want to get the number, you have to convert them from a string.

This means you have to read the file, you can do this with read() if you want, and store the content in a char array, add a NUL-Byte and then convert the resulting string with a function like strtol() or sscanf().

What you are doing

What you do is reading the ASCII characters into the int len. When you use a debugger before the write() call, you can check the value of len. In my case i used this as an input file:

0
1
2
3
...

When i stop my debugger before write(), i see that len has the value of 170986032 == 0xA310A30. My system is little endian, means the lowest byte is stored at the lowest address (unlike my previous example). Which means 0x30 comes first, then 0x0a, 0x31 and 0x0A. From this we know that we got the following memory layout of len.

Address Offset   0x00  0x01  0x02  0x03
Value            0x30  0x0A  0x31  0x0A
Text                0    LF     1    LF

As you can see, the text is interpreted as a int.

How to get what you want

You want to store the data into a char array. And then parse it. I use some pseudo code to explain it better. This is not C-Code. You should learn to write your own code. This is just to get you an idea what you have to do:

char buffer[<buffersize>] //create a buffer array
r=read(buffer) //read the file into the buffer. You may need to repeat that multiple times to get everything
if r==error //check for errors
  <do some error handling here>
buffer[<one after the last read byte>]='\0' //add the NUL-Byte st the end, so that we have a string.
int values[<number of ints you want>]  //create an array to store the parsed values
for(<one loop for every int>) //make the loop for every int, to parse the int
  values[<index>]=strtol(buffer,&buffer,0) //parse the text to a int
  if error occured:
    <do some error handling here>

How to implement this in C is your task. Keep buffer sizes in mind so you do not end with UB.

0
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

int main()
{
    int fd;
    char arr[10000];
    int arr2[10000];
    ssize_t count;
    fd = open("1.txt", O_RDONLY);
    if (fd >= 0)
    {
        count = read(fd, arr, 10000); // reading from file and writing to array.
        if (count == -1)
        {
            printf("Error %d\n", errno);
            exit(0);
        }
        arr[count] = '\0';
    }

    for(int i=0; i<count; i++)  //Converting the character arrays to integer array
    {
        if(arr[i] >='0' && arr[i]<='9' )
        arr2[i] = arr[i]-'0';
        else
        {
            arr2[i] = 0; //For characters other than numbers.
        }
        
    }

    for (int i=0; i<count; i++)
    {
        printf("%d ",arr2[i]);
    }

    close(fd);

    return 0;
}

Here, I read the numbers from the file and stored into a character array, then I converted it to an integer array. If there is any character other than number, I am assigining it as zero here in the array.

Krishna Kanth Yenumula
  • 2,533
  • 2
  • 14
  • 26
  • i was tried this before and unfortunately it's not working – ofbahar Nov 27 '20 at 15:03
  • Yes. but array should be integer – ofbahar Nov 27 '20 at 15:08
  • It does not work that way when the input file is a text file, as it is. It would only work when the input is a binary file containing the `int`'s in binary form. And in this case you have to multiply the number by `sizeof(int)`. And you have to check the return value. – 12431234123412341234123 Nov 27 '20 at 15:11
  • 1
    @KrishnaKanthYenumula It still does not work for text files. You solution now works for binary files in the correct format. And besides that you still don't check the return values. Anyway, your code is will not work for the task without rewriting most of it completely. – 12431234123412341234123 Nov 27 '20 at 15:18
  • @KrishnaKanthYenumula You interpret every character and digit individually but a number like `42` uses two digits. The `int` you use does not actually store the number. Every character that is not a digit leads to a gap in `arr2` where a element is not set which causes UB. – 12431234123412341234123 Nov 27 '20 at 16:22
  • I have to admit, your code is quite creative. But not what we are looking for. – 12431234123412341234123 Nov 27 '20 at 16:23
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/225218/discussion-between-krishna-kanth-yenumula-and-12431234123412341234123). – Krishna Kanth Yenumula Nov 27 '20 at 16:23
  • I get segmentation fault. Then debug with gdb and i see error 14 – ofbahar Nov 27 '20 at 16:38
  • @ofbahar Sorry, there was a bug. I fixed it. Please check now. – Krishna Kanth Yenumula Nov 27 '20 at 18:03
  • @12431234123412341234123 OP mentioned that text file contains only numbers. So UB will not happen. I am checking if the character is a number or not, then only I am assigning it to the integer array. `42` is two digits, but I am reading `4` and then `2`. So I think this will not create a problem. – Krishna Kanth Yenumula Nov 27 '20 at 18:06
  • @12431234123412341234123 Suppose '1' is stored in `char` array, then I am storing '1' - '0' in `int ` array, which is 49-48 =1 (ASCII of 0 is 48, ASCII of 1 is 49). I think result 1 is a number. – Krishna Kanth Yenumula Nov 27 '20 at 18:09