reading data from txt file.

Dec 23, 2017 at 3:55pm
Hey everyone, I'm trying to create a basic program that reads data from a txt file
that looks like this:
/* data.txt */
var1 = value1
var2 = value2
var3 = value3
var4 = value4
/************/

and store these variables and their values into an array of chars.
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

int main(int argc, char *argv[])
{
char *grid = (char*)malloc(9 * 9);

FILE* f_read = fopen("data.txt", "r");

int i = 0;

char tempGrid[128];
while (fscanf(f_read, "%c", &tempGrid[i]))
{
// what should i add here?
i++;
}

free(grid);
fclose(f_read);

return 0;
}
Dec 23, 2017 at 4:29pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <fstream>
#include <string>
#include <map>
using namespace std;

//======================================================================

string trim( string s, string junk )
{
   int i = s.find_first_not_of( junk );
   if ( i == string::npos ) return "";

   int j = s.find_last_not_of( junk );
   return s.substr( i, j - i + 1 );
}

//======================================================================

int main()
{
   string filename = "data.txt";
   map<string,string> myThings;        // this will hold variable name and value
   string name, value;

   ifstream in( filename );
   while ( getline( in, name, '=' ) )  // try reading up to '=' (which is then discarded)
   {
      getline( in, value );   if ( !in ) break;

      name  = trim( name , " " );           // remove start and end blanks if required
      value = trim( value, " " );

      myThings[name] = value;          // assign to an associative container (map)
   }
   in.close();

   cout << "Read " << myThings.size() << " items, as follows:\n";
   cout << "Name\tvalue\n";
   for ( auto e : myThings ) cout << e.first << '\t' << e.second << '\n';
}

//====================================================================== 


Read 4 items, as follows:
Name	value
var1	value1
var2	value2
var3	value3
var4	value4

Dec 23, 2017 at 4:32pm
thank you @lastchance. but i am trying to get the vars and values using fscanf or fread.
I know it would be complicated a little but i have to do it.
Last edited on Dec 23, 2017 at 4:34pm
Dec 23, 2017 at 4:32pm
Why?
Dec 23, 2017 at 4:45pm
university...
Dec 23, 2017 at 6:12pm
Does your file actually contain two strings separated by an equals sign, or does it contain a "name" followed by an equal sign and then a numeric value?



Dec 23, 2017 at 9:24pm
Um, Q is in C.

First, a little helper function:

1
2
3
4
5
char* zero( char* p )
{
  if (p) *p = '\0';
  return p;
}

Now you can write a function to read your file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
bool read_vars( const char* filename )
{
  char s[ 128 ];
  char* p;

  FILE* fp = filename ? fopen( filename, "r" ) : stdin;
  if (!fp) return false;

  // while we can read a line from the file
  while (fgets( s, sizeof( s ), fp ))
  {
    zero( strchr( s, '\n' ) );

    // split the line into name and value
    if (zero( p = strchr( '=' ) )) ++p;
    char* name  =     trim( s );
    char* value = p ? trim( p ) : NULL;

    // add the name,value to your dictionary
    ...
  }

  fclose( fp );
  return true;
}

You can find a variety of ways to trim a string in the FAQ: http://www.cplusplus.com/faq/sequences/strings/trim/#c. I would use the inplace/advance versions for this particular piece of code.

I don't know how you plan to implement your dictionary, but the current grid thing you are attempting to do won’t work well. A very simple alternative is to use an array of struct:

1
2
3
4
5
6
7
8
9
10
typedef struct
{
  char* name;
  char* value;
}
pair;

const int NVARS = 100;
pair vars[ NVARS ];
int nvars = 0;

Thereafter, to add a (name,value) pair to your dictionary, just append it.

1
2
3
4
5
6
7
8
9
void add_var( const char* name, const char* value )
{
  if (nvars < NVARS)
  {
    vars[ nvars ].name  = strdup( name );
    vars[ nvars ].value = strdup( value );
    nvars += 1;
  }
}

Be sure to clean up properly when destroying the dictionary:

1
2
3
4
5
6
7
8
9
void free_vars()
{
  for (int n = 0; n < nvars; n++)
  {
    free( vars[ n ].name );
    free( vars[ n ].value );
  }
  nvars = 0;
}

Having a handy way to find a pair is also useful:

1
2
3
4
5
6
7
8
9
10
// Find an item in the dictionary.
// Returns nvars if not found.
int find_var( const char* name )
{
  int n;
  while (n < nvars)
    if (strcmp( name, vars[ n ].name ) == 0) break;
    else n += 1;
  return n;
}

The only limitation is the fixed size of an array. You could make it a dynamic array, and resize when necessary. Another easy option would be to use a linked list.

Whatever you choose, I would make an ADT to handle it. A good one might look like:

1
2
3
4
5
6
7
8
9
bool        dictionary_create(  dictionary* );
void        dictionary_destroy( dictionary* );
size_t      dictionary_size(    dictionary* );
bool        dictionary_set(     dictionary*, const char* key, const char* value );
const char* dictionary_get(     dictionary*, const char* key );
void        dictionary_unset(   dictionary*, const char* key );

dictionary_iterator dictionary_first( dictionary* );
dictionary_iterator dictionary_next(  dictionary_iterator );

It could be used like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int main()
{
  dictionary dict;

  if (!dictionary_create( &dict )) return 1;

  dictionary_set( &dict, "birds",  "7" );
  dictionary_set( &dict, "cats",   "9" );
  dictionary_set( &dict, "humans", "2" );

  // The humans go out to lunch
  dictionary_unset( &dict, "humans" );

  printf( "There are %lu items in the dictionary:\n", (unsigned long)dictionary_size( &dict ) );
  dictionary_iterator iterator = dictionary_first( &dict );
  while (iterator)
  {
    printf( "  %s = %s\n", iterator->key, iterator->value );
    iterator = dictionary_next( iterator );
  }

  printf( "Oops, that was too many cats. Let's fix that:"
  dictionary_set( &dict, "cats", "3" );
  printf( "  cats = %s\n", dictionary_get( &dict, "cats" ) );

  dictionary_destroy( &dict );

The output:
There are 2 items in the dictionary:
  cats = 9
  birds = 7
Oops, that was too many cats. Let's fix that:
  cats = 3

Implementing these kinds of functions is really easy. More importantly, it makes using your dictionary so much easier.

Hope this helps.
Last edited on Dec 23, 2017 at 9:26pm
Dec 24, 2017 at 10:11pm
Yeah that's what i'm talking about, you got skills.
Last edited on Dec 24, 2017 at 10:12pm
Dec 25, 2017 at 9:12am
Nah, people aren’t taught how to use C properly, so it looks like magic when you see it. But, you’re welcome. Keep on learning! :O)
Topic archived. No new replies allowed.