Ahmad Khateeb
Ahmad Khateeb

Reputation: 73

Slicing file string

I have a text file that holds ID's and names all in one line

314 name1   122 name3   884 name2

the ID is 3 digits (we will deal with it as char), then we have one space followed by the name which is 8 digits (spaces included), and then comes another person's ID/name and so on...

so I open a the file, read it and want to "slice" it

*the struct I am about to mention isn't important, just an example, can be found at the bottom

Basically take the first 3 digits and put them in a struct under ID, then ignore the following space, and grab the 8 digits that come after and place them in the same struct under name and so on (can just remove the first 12 digits of the file every time), the problem is simply the slicing

I came from Python where if I have a string, and only want to keep the first two digits I'd do something like string = string[0-2]

//ProductTree is a struct 

char initial_s[sizeof(initialStockFile)];
ProdudctTree* temp = NULL;
fscanf(initialStockFile, "%s", initial_s);
        temp = malloc(sizeof(ProductTree));
        while( initial_s != '\0' ){
            temp->id = initial_s[0-9];
            temp->productName = initial_s[10-20];
            initial_s = initial_s+21;
            temp = temp->right;
        }
        temp->right = NULL;
        return temp;

This is what I have tried but clearly doesn't work

The struct if anyone is curious

typedef struct ProductTree {
    char* id;               //Product ID number. This is the key of the search tree.
    char* productName;      //Name of the product.
    struct ProductTree *left, *right;
} ProductTree;

Upvotes: 0

Views: 175

Answers (2)

SiggiSv
SiggiSv

Reputation: 1229

Since you're coming from Python, strtok(char *str, const char *delim), which has been mentioned here, does a similar job as string.split(s[, sep[, maxsplit]]) does in python (with some differences like: There is no default delimiter. It does not return a list of strings. It just returns the first splice and then you need to call it again with str set to NULL).

But there is no need to use any function that search through the string for some separator since you know that you want to slice the file into strings that are each 12 char long (and then slice each of them into a string containing the first 3 char and a string containing the last 8 char, discarding the one char between them).

For the first part, slicing the file into strings that are 12 char long, you have two options:

  • You could use fgets(tmp_str, 13, filename) to read 12 char at once from the file (size is 13 because it reads in one less char than size because it then need one more to end the string with '\0').
  • Or you could read all the file into a string. Then in a loop, use strncpy(tmp_str, &initial_s[i * 12], 12) (assuming i is our counter, starting at 0 and the file was read into initial_s) to copy 12 chars, starting at position i * 12 into tmp_str (and don't forget to terminate the string with tmp_str[12] = '\0'.

For the second part, you again have two options:

  • You could again use strncpy(). This time to first copy 3 chars into temp->id, starting at the begging of tmp_str. And then to copy 8 chars into temp->productName, starting at position 4 (remember to terminate all your strings with '\0'). If you do so, you could change your struct to have char arrays instead of pointers to chars:

    typedef struct ProductTree {
        char id[4];               //Product ID number. This is the key of the search tree.
        char productName[9];      //Name of the product.
        struct ProductTree *left, *right;
    } ProductTree;
    
  • Or you could be a bit "clever" for the second part. Have temp->id point to the beginning of tmp_str , have temp->productName point to the 5th char in tmp_str and change the space between them to '\0' to terminate temp->id:

    temp->id = tmp_str;
    tmp_str[3] = '\0';
    temp->productName = tmp_str[4];
    

Whichever options you chose, remember to allocate memory for all your strings, check all input for errors and free both your strings and structs when done.

Upvotes: 1

Ra'Jiska
Ra'Jiska

Reputation: 1049

You may want to use the LibC strtok function. It allows you to split your string given a list of separators.

Here is an example similar to your project:

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

int     main(int argc, char **argv)
{
  int   i;
  char  *line;
  char  *tok;

  i = 0;
  if (!(line = strdup("123 Hello 345 World 678 Foo 901 Bar")))
    return EXIT_FAILURE;
  tok = strtok(line, " ");
  while (tok)
    {
      if ((i % 2) == 0)
        printf("ID: ");
      else
        printf("Name: ");
      puts(tok);
      tok = strtok(NULL, " ");
      ++i;
    }
  free (line);
  return EXIT_SUCCESS;
}

Which outputs:

ID: 123
Name: Hello
ID: 345
Name: World
ID: 678
Name: Foo
ID: 901
Name: Bar

Upvotes: 0

Related Questions