Reading text file into array using Scanner: Null Pointer Exception - arrays

Im trying to read an archive file and pass it to an array but i keep getting Null Pointer Exception when i try to access to array[0]. When i asked java to print array[0] it shows null. This is the way i read the text file:
int lines= 0;
while(s1.hasNext()) {String line=s1.next(); lines ++; } // The number of lines
int i= 0;
char [][] array= new char [lines][];
if (f.exists()) {
while (s1.hasNext()) {
String line= s1.next();
int m = line.length();
for (int j = 0; j < m; j++) {
array[i][j]=line.charAt(j);
}
i++;
}
}

array[0] must be null, because you haven't allocated memory for that.
There are some more problems:
The second while(s1.hasNext()) loop will never be executed, because the first one will read through the whole file, and when that ends, s1.hasNext() will return false. So the second loop will never run.
array is initiated with lines number of char arrays, but none of the arrays are initialized. So they all are null. When you try to access any of them, certainly you'll get a NullPointerException!

Related

Using strstr with 2d array

I'm programming in C. I have loaded a 2d array with words. It is called dictionary[][]. I am trying to use strstr to find out how many of the words have a substring in them of "struct". Here is the code. In my function count_matches I try to iterate through dictionary using the strstr function to compare. It always returns null so I never get to ++matchcount. Any ideas why?
Here is the function. inp is "struct" dictionary is the 2d array and n is the number of lines in the array (I.e. how many words are in the array).
int count_matches(char *inp, char dictionary[MAX_LINES][MAX_LEN], int n)
{
int matchcount = 0;
int i;
for (i=0; i < n; ++i)
{
if (strstr(dictionary[i], inp) !=NULL)
{
++matchcount;
}
}
return matchcount;
}
I don't see your problem in the given code snippet.
Think about the following:
Did you mix up MAX_LINES and MAX_LEN?
Is the inp really equal to "struct"?
Did you load the dictionary with at least one word that has the substring "struct"?
Show the code where you make the call to this function if the problem persists.
For example, this works fine:
int main()
{
char dictionary[MAX_LINES][MAX_LEN] = {"hello", "hihello", "bye", "Hello"};
int output = count_matches("hello", dictionary, 4);
printf("%d", output); // Output is 2 as expected
return 0;
}
By the way, you can also consider making the following changes to your code:
MAX_WORDS is more readable than MAX_LINES
You do not necessarily have to write != NULL inside that condition

Shifting elements in array of strings, C

I want to shift each string in an array of strings one element to the left:
char historyArray[HISTORY_DEPTH][COMMAND_LENGTH];
Neither of my two attempts below work. Can someone explain to me what I'm doing wrong?
for (int i = 1; i < HISTORY_DEPTH; i++) {
strcpy(historyArray[i-1], historyArray[i]);
}
for (int i = 1; i < HISTORY_DEPTH; i++) {
historyArray[i-1] = historyArray[i];
}
define historyArray as char *historyArray[HISTORY_DEPTH]; This defines historyArray as an array of character string pointers. Then historyArray[0] points to teststring as a result of the assignment. As an array of pointers, you can handle each string pointer properly. You can then malloc a buffer pointer to use as an element in the array. and use strcpy to copy into that buffer.
char *historyArray[HISTORY_DEPTH];
// put initialization code here
for (int i = 1; i < HISTORY_DEPTH; i++) {
historyArray[i-1] = historyArray[i];
}
historyArray[HISTORY_DEPTH-1] = NULL; //empty the last element pointer
This now moves the pointers into the previous element of the array.
Note that the original contents of historyArray[0] are now lost which would cause a memory leak if you had used malloc to create it. As a result, it should have had a free() applied to it. If it was a fixed buffer and does not need to be freed then you would not have to worry about it.
char historyArray[HISTORY_DEPTH][MAX_SIZE];
for (int i = 1; i < HISTORY_DEPTH; i++) {
// Or use the memset with strlen(size+1)
// to ensure that the ending '\0' is also copied
strcpy(historyArray[i-1], historyArray[i]);
}
historyArray[HISTORY_DEPTH-1][0] = '\0'; // make the last an empty string
The strcpy of the second, will copy the contents of each string pointed to by historyArray into the buffer pointed to by the previous element without moving the pointers themselves. This assumes that each buffer is large enough to hold the character string. The last pointer continues to also hold the same data as it did before unless you put in an empty string.
Are you saying that if you have a string like
aaa, bbb, ccc
You want
aaa, ccc, ccc
as the result? Because your index starts at 1, which I suspect is not your intention. If it is the case, this can get you bbb, ccc, ccc using this
for (int i = 0; i < HISTORY_DEPTH-1; i++) {
strcpy(historyArray[i], historyArray[i+1]);
}

Do operation on each in dynamic array

Suppose I have a struct
struct point_2d {
int x,
int y
};
Suppose in my program I keep an array of this type,
main()
{
struct point_2d *coords = malloc(10*sizeof(struct point_2d));
...
}
and I want to do an operation on each of them (for example, set all points' coordinates to the origin or something).
Is there a way to loop through without having to know the length of the array (such as with strings, incrementing the pointer until \0 is encountered), or do I need further input to determine that length?
Is there a way to loop through without having to know the length of the array (such as with strings, incrementing the pointer until \0 is encountered), or do I need further input to determine that length?
There is no way to loop without knowing how far to loop, unless you add a sentinel value to your array just as is done with C-strings and the \0 termination. Even the foreach() loop in C++ has to aquire an iterator past the end of the container to know how far to loop.
Assuming, you allocated the memory with
int size = 10;
struct point_2d* coords = malloc(size*sizeof(*coords));
I'd recommend iterating through arrays with one of the following loop constructs:
Forward:
for(int i = 0; i < size; i++) coords[i].x = coords[i].y = 0;
Backwards:
for(int i = size; i--; ) coords[i].x = coords[i].y = 0;
That's hardly more to write than with a foreach() loop in other languages, and you see precisely what's happening.

Input and output array don't match

I am writing a program for a class at school and I cannot get the program to print out what I type in.
The problem states that the first line needs to contain the number of questions on an 'exam' followed by a space then the answer key. I wanted to print the answer key to make sure that it was being entered in correctly and it never matches what I type in. The code is posted below.
This is the main file that starts being run and it calls a method from another file I have made the prototype file correctly so I'm pretty sure it's not that.
int main()
{
int i;
int noOfQuestions;
scanf("%d ", &noOfQuestions);
char * answerKeyPtr;
answerKeyPtr = fgetAnswers(noOfQuestions);
for(i = 0; i < noOfQuestions; i++){
printf("%c",answerKeyPtr[i]);
}
printf("\n");
return 0;
}
char *fgetAnswers(int noOfQuestions){
int i;
char * answerKeyPtr;
char AnswerKey[noOfQuestions];
answerKeyPtr = AnswerKey;
for(i = 0; i < noOfQuestions; i++){
scanf("%c",&AnswerKey[i]);
}
return answerKeyPtr;
}
What you have here is a memory problem.
You're storing data into the AnswerKey array, which is local to fgetAnswers(). The problem is you're returning a pointer to that local variable, and that variable's memory is not reliable as soon as your fgetAnswers() function finishes that memory should not be accessed. So when you try to print the data in main() you're accessing memory you shouldn't.
To solve it, create the AnswersKey array in main, and pass it as a parameter to the fgetAnswers() function.
The char array AnswerKey is allocated on the stack when fgetAnswers is called. When you return from fgetAnswers, data stored in the stack frame for that call is no longer valid. You'll need to pass in the array or alloc it so the input isn't stored in the stack.

New Arrays and Pointers

I am having a bit of trouble because I am new to C and am not even sure if what I want to do is possible.
I am passing an array called args into a function. Within the function I am also creating a 2D array called arrayOfArgs. What I want to do is to put certain values from args into specific locations in the 2D array called arrayOfArgs.
This is my code so far:
int do_command(char **args){
//this is usually a changing variable depending on the situation, but I've hard coded it to make sense
int commands = 3;
char **arrayOfArgs[commands][10];
//counts which column in arrayOfArgs we are on
int commandNum = 0;
//Counts which part of a command we are on
int count = 0;
//Array Counters
int i = 0;
int j;
//Go through args until we reach the end
while (args[i] != NULL){
if(!strcmp(args[i], "|")){
arrayOfArgs[commandNum][count] = args[i];
count++;
}
else if (strcmp(args[i], "|")) {
count = 0;
commandNum++;
}
//Looking at the next value in args
i++;
}
I'm running into problems because the only thing being put into arrayOfArgs is gibberish. I'm sure I've done something wrong with either the way the arrays are pointing, the way arrayOfArgs was created, or both.
OR is it even possible to go from a 1D to a 2D array like I'm trying?
I'm pretty sure there is a NULL there because earlier I call this loop and it works:
for(i = 0; args[i] != NULL; i++) {
printf("Argument %d: %s\n", i, args[i]);
}
Thanks!
First of all, how are you verifying that the contents of arrayOfArgs are gibberish? Are you printing out the contents with printf? Are you using a debugger?
Second of all, what is each element of arrayOfArgs supposed to store? Is it supposed to be a 3-element array of strings 9 characters or less? Is it supposed to be a 3x10 element array of pointers to char? Is it supposed to be a 3x10 element array of pointers to pointers to char?
In the line
arrayOfArgs[commandNum][count] = args[i];
the expression args[i] has type char *; that strongly implies that you intend for each element of arrayOfArgs to store a char *. In that case, change the declaration of arrayOfArgs to
char *arrayOfArgs[commands][10];
(I read this as each command can have up to 9 arguments).
IOW, it looks like you're trying to store something like
col 0 1 2 3 4 5 6 7 8 9
row
0 "cmd" "a1" "a2" NULL NULL NULL ...
1 "cmd" "a1" NULL
...
by storing pointers to each string in the 2D array.
If that's the case, then you need to change the declaration of arrayOfArgs as I said above. If that's not the case, then you need to give us an example of what arrayOfArgs is supposed to look like.
So I see some issues...
First I believe you mean to have char arrayOfArgs[commands][10]; as you want a 2D array of 10 character strings (i assume this is what you want)... otherwise it would be a 2D array of an array of string pointers (so like a 4D array of characters :P)
Next the code you have created will only copy into each of those command buffers the character | if the argument itself is |
If you are looking for the contents between the pipe symbols look into the function strchr and strncpy, with these functions I would loop through each arg and if and argument is the pipe symbol, |, find the next argument with the pipe symbol, loop through the arguments in between and then copy the characters in between into a dynamically allocated char array
Also, in your comments you say that the commands array will be dynamic... the way you have your program structured the data is statically allocated on the stack. To make this dynamic you will need to dynamically allocate onto the heap i.e. malloc/calloc
The problem is here:
char **arrayOfArgs[commands][10];
This declares an two dimension array of double char pointers, which is not what you want.
Try the following instead:
char *arrayOfArgs[commands][10];
EDIT: changed to char* because after examine the code I found the OP assigning a pointer to a character array to arrayOfArgs. Thanks to #wildplasser for notifying.
I figured it out. I decided to go a 1D array route rather than a 2D way. The code now takes args, which were split before as "ls" "-l" "|" "wc" and separates them based on if there is a pipe into a new array called "arrayOfCommands". The contents of arrayOfCommands are then, once this is through, "ls -l" and "wc". Here's the code:
int do_command(char **args,) {
const int commands = 2;
int i = 0;
int commandNum = 0;
int firstCommand = 1;
char *arrayOfCommands[commands];
//Go through args until we reach the end
while (args[i] != NULL){
//First case
if(firstCommand){
arrayOfCommands[commandNum] = args[i];
firstCommand = 0;
}
//Rest of the cases
else{
//if we find something that's not a pipe...
if(strcmp(args[i], "|")){
//Add a space to what was a previous part of the same command
arrayOfCommands[commandNum] = strcat(arrayOfCommands[commandNum]," ");
arrayOfCommands[commandNum] = strcat(arrayOfCommands[commandNum],args[i]);
}
//But if we do find a pipe...
else if (!strcmp(args[i], "|")) {
//We know it's time for a new command
commandNum++;
firstCommand = 1;
}
}
//Looking at the next value in args
i++;
}
for(i = 0; i < commands; i++)
printf("Command #[%d]: %s\n", i, arrayOfCommands[i]);
}

Resources