Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help with inputting multidimensional string arrays....
#41
Thanks, but that still doesn't stop the unhandled exception crash. Check out the function make_word and look for the remmed line. The char *finame makes the program crash, and last I checked making a character pointer is perfectly legal.

here's some stuff I found that I don't understand (the third one shows the exact same 0x000.... message I get:

http://support.microsoft.com/default.asp...bContent=1

http://msdn.microsoft.com/library/defaul...ptions.asp

http://www.experts-exchange.com/Programm...12651.html
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#42
Code:
filename = (char *) malloc(sizeof(strlen(finame)));

isn't sizeof(strlen(finame)) calculating the size of the return value of strlen? Shouldn't you just say sizeof(finame) or strlen(finame) + 1?
Reply
#43
Okay, for some reason it will go through with the char * command, but it is really getting hung up on inputting stuff like cin << word->theword:

Code:
typedef struct {
     string theword, definition;
     int clues;
} word_struct;

word_struct *word;
char *clues;

word = (word_struct *) malloc(sizeof(word_struct));
int ii;
char *finame;
char tmpc[60];
system("cls");
cout << "Word: ";
//cin >> word->theword;
cout << endl << "Definition: ";
cin.getline(tmpc, 59);
word->definition = string(tmpc);
cout << endl << "Clues: ";
cin >> word->clues;
clues = (char *) malloc(word->clues * sizeof(char[60]));
for (ii = 0; ii < word->clues; ii++) {
     cout << "clue " << ii;
     cin.getline(tmpc, 59);
     strcpy(&clues[ii], tmpc);
}
strcpy(tmpc, "word01.dat");
finame = (char *) malloc(sizeof(strlen(tmpc) + 1));
finame = "word01.dat";
FILE *f;
f = fopen(finame, "w");
if (!f) return 1;
     fprintf(f, "%s%s%d", word->theword, word->definition, word->clues);
for (ii = 0; ii < word->clues; ii ++)
     fprintf(f, "%s", clues[ii]);
fclose(f);
free(finame);
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#44
Quote:Isn't sizeof(strlen(finame)) calculating the size of the return value of strlen? Shouldn't you just say sizeof(finame) or strlen(finame) + 1?
Good point, I must be asleep at the wheel again. sizeof returns the byte size of its argument, so:
Code:
sizeof(strlen(finame) + 1);
Will always return 4 (on the x86) because strlen returns an integer, sizeof then returns the size of an integer which is four bytes. So, as DrV said you should instead use:
Code:
strlen(finame) + 1;
or
Code:
sizeof(finame);
Will also work, but slightly differently. strlen will return the actual length of the string in the array, so if finame was defined as char finame[40] = "Hello World", strlen will return a length of 11, but sizeof will return a size of 40. Which method you want to use will depend on your code.

Thanks for pointing that out DrV.

Sorry Typosoft, I don't know how cout and cin and the string type work, they are C++ inventions. I personally use functions like scanf, sprintf, strcat etc for manipulating strings.
esus saves.... Passes to Moses, shoots, he scores!
Reply
#45
hey, scanf worked just fine! Now I have a problem with getline (isn't it supposed to read a whole line of text including whitespace).
here's my code:

Code:
char tmpc[60];
getline(tmpc, 59, "/n");

here's my compiling errors
Quote:C:\Program Files\Microsoft Visual Studio\MyProjects\guess that word\guess that word.cpp(121) : error C2784: 'class std::basic_istream<_E,_Tr> &__cdecl std::getline(class std::basic_istream<_E,_Tr> &,class std::basic_string<_E,_Tr,_A> &,const _E)' :
could not deduce template argument for 'class std::basic_istream<_E,_Tr> &' from 'char [60]'
C:\Program Files\Microsoft Visual Studio\MyProjects\guess that word\guess that word.cpp(121) : error C2780: 'class std::basic_istream<_E,_Tr> &__cdecl std::getline(class std::basic_istream<_E,_Tr> &,class std::basic_string<_E,_Tr,_A> &)' : expects 2
arguments - 3 provided
c:\program files\microsoft visual studio\vc98\include\string(145) : see declaration of 'getline'
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#46
I dont know how getline works, its not Standard C because C has no concept of lines of text, it views input and output simply as streams.

You could try using fgets, which reads characters from a given stream until it hits either a newline, EOF or the specified length. To read an 80 character line you would use it thusly (untested):
Code:
#define TEXT_WIDTH 80

char *readLine() {
  char *string;
  
  /* Allocate memory for the string */
  string = (char *)malloc(TEXT_WIDTH * sizeof(char));
  
  /* Get a line of text */
  fgets(string, TEXT_WIDTH, stdin);

  /* Return the string */
  return string;
}
esus saves.... Passes to Moses, shoots, he scores!
Reply
#47
fgets works awesomely, but here is a better working example:

Code:
char *cptr;
char buffer[256];
  
printf("Enter some stuff:\n");
cptr = fgets(buffer, 256, stdin);
if(cptr != NULL) {
     printf("You typed : %s\n", cptr);
}

I now have another problem about how to make an array of strings. I need to have an array of strings so I'm guessing I need a double pointer? Here's what I have (doesn't work)

Code:
char *clue[10];
char tmpc[256];
int ii;

for (ii = 0; ii < word->clues; ii++) {
     while (!clue[ii]) {
          cout << endl << "   clue " << ii << ": ";
          clue[ii] = fgets(tmpc, 256, stdin);
      }
}

Also, can I define char tmpc on the same line as *clue[10] without any problems (because it's a char *)?
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#48
You will need to malloc each of the strings in your array:

Code:
/* This gives us an array of 10 pointers to char, or ten strings */
int i;
char *clue[10];
/* Malloc each of the strings to size 256 */
for(i = 0; i < 10; i++) {
  clue[i] = malloc(256 * sizeof(char));
}
Then the rest of your code should work correctly. Remember to free each of the clues when you are done with them.

Quote:Also, can I define char tmpc on the same line as *clue[10] without any problems (because it's a char *)?

Sure, the following is perfectly valid:
Code:
char character, *string, **arrayOfStrings, char *(*function)(char *);

Which defines a single char, a pointer to char, a double pointer to char and a pointer to a function which takes a pointer to char and returns a pointer to char. Whew ;-)
esus saves.... Passes to Moses, shoots, he scores!
Reply
#49
cool it worked. I want to input strings and numbers and test to see if the appropriate items were entered and if not loop until they are. My testing and looping for the number of clues works, but the testing and looping for the strings doesn't. I thought using: while (!strlen(word->theword) would work, but no dice (unhandled exception).

Code:
while (!word->theword) {
        cout << endl << "Word: ";
        word->theword = fgets(tmpc, 80, stdin);
    }
        
    while (!word->definition) {
        cout << endl << "Definition: ";
        word->definition = fgets(tmpc, 80, stdin);
    }
        
    while (!word->clues || word->clues > 10) {    
        cout << endl << "Clues (1-10): ";
        scanf("%d", &word->clues);
    }
    
    for (ii = 0; ii < word->clues; ii++) {
        while (!clue[ii]) {
            cout << endl << "   clue " << ii << ": ";
            clue[ii] = fgets(tmpc, 80, stdin);
         }
    }
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#50
In C values are not automatically initialised when they are declared, so they just cannot some random, usually very large number. Pointers are worse, because they just point to some random memory location until they are explicitly initialised, which could be the location of some other variable or even part of the operating system. Attempting to derefernce an unitialised pointer will result in a segmentation fault (Cant remember what Windows calls it). So calling strlen on a string that may not have been initilaised is a really bad idea.

Instead you could try making the strings point to NULL to begin with and then test if they have been initialised and what there length is, ie:
Code:
char *word = NULL;

/*
* Take advantage of lazy evaluation, if word == NULL the second part
* of the expression will not be evalutated.
*/
while(word == NULL || strlen(word) == 0) {
  /* Cout is gross ;-) */
  printf("Word: ");
  word = fgets(tmpc, 80, stdin);
}

This will only test for null or zero length strings though, if you want to prevent users from entering blank strings (say a string consisting of a tab character and 10 spaces) or from entering invalid characters then you will need to write your own string parsing functions or find a library that provides the ones that you need.
esus saves.... Passes to Moses, shoots, he scores!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)