New Arrays and Pointers - c

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]);
}

Related

How to put strings from a file into an array in c

So I have this code:
char inte[10];
while(j<noinput) {
fscanf(circuit,"%s",inte);
vararray[count]=inte;
count++;
j++;
}
However when I print the contents of the array like this:
for (h=0;h<noinput+2;h++){
printf("%dth variable: %s\n",h,vararray[h]);
}
The elements past the first two (which are reserved for special elements) are all equal to the LAST string that I had taken in from fscanf earlier. I have no idea how one of the strings from fscanf could be equal to multiple slots in the array when I am only setting
vararray[count]=inte;
Shouldn't this mean that each element of the array will be different since I am incrementing count every time? I am so confused. I also tried doing:
fscanf(circuit,"%s",vararray[count]);
But this also did not work and gave me null elements for certain indexes.
you are doing something too wrong. By "vararray[count]=inte;" you are doing pointer assignment so all of your vararray is getting filled by same string. I am guessing you are new to C so I will answer due to that. Correct way would look something like below
Fixed size solution:
char vararray[ROWCOUNT][BUFFERSIZE];
for(count=0; j<noinput; ++count, ++j) {
fscanf(circuit,"%s",(char*)vararray[count]);
}
With dynamic memory management
char * vararray[ROWCOUNT];
for(count=0; j<noinput; ++count, ++j) {
vararray[count] = (char*)malloc(BUFSIZE);
fscanf(circuit,"%s", vararray[count]);
}
I want to warn you in the way of becoming an expert on C nowadays is somewhat madness , i mean unless you have another choice. Examples below I put and the thing you wrote are completely unsafe and unsecure...
You're not copying the string. Here's what's happening:
char *vararray[462]; // declare an array of string pointers
char inte[10]; // declare a char array (to function as a string)
for (int i = 0; i < 462; i += 1) {
// do something
vararray[i] = inte;
}
This is causing all of the items of vararray to point to the memory also referred to as inte... but you're overwriting that each time! Instead, do something like this:
#include <string.h> // write me at the top, outside main()!
char vararray[462][10]; // declare an array of strings (max length 9)
char inte[10]; // declare a char array (to function as a string)
for (int i = 0; i < 462; i += 1) {
fscanf(circuit,"%10s",inte); // use buffer size to make xscanf safer
strncpy(vararray[i], inte, 9); // copy inte, making sure not to buffer overflow!
vararray[i][9] = '\0'; // if inte is too big, a null byte won't be added to the end of the string; make sure that it's there
}
This copies the string! Your problem should go away when you do this.

String array of n dimensions - c

I want to know how to create a dynamic array of 2 strings per array. And I'm not sure how. I know how to create an array of strings, but not one of "n" dimensions, and i want to know how.
Here are some parts of my code, which is just currently an array of strings:
First I declared my array inside an struct:
typedef struct{
char bloqueCedula[7];
short bloqueDia;
char **bloqueLibrosPrestados;//This is the array i want to modify
}RegistroControl;
then I initialize it on my first registration:
void primerRegistro(RegistroArchivo regArch, RegistroControl *regControl) {
strcpy(regControl->bloqueCedula, regArch.cedula);
regControl->bloqueDia = regArch.dia;
regControl->bloqueLibrosPrestados = malloc(cont * sizeof(regControl->bloqueLibrosPrestados));
regControl->bloqueLibrosPrestados[0] = malloc(7 * sizeof(char));
strcpy(regControl->bloqueLibrosPrestados[0], regArch.codigoLibro);
imprimirCabecera();
//printf("%s\n", regControl->bloqueLibrosPrestados[cont-1]);
}
In the code above I made each string of a length 7, because I already know the length of what I need to copy on it, which is 6.
This is how I kept making it grow:
void procesarRegistro(RegistroArchivo regArch, RegistroControl *regControl) {
cont++;
regControl->bloqueLibrosPrestados = realloc(regControl->bloqueLibrosPrestados,cont * sizeof(regControl->bloqueLibrosPrestados));
regControl->bloqueLibrosPrestados[cont-1] = malloc(7 * sizeof(char));
strcpy(regControl->bloqueLibrosPrestados[cont-1], regArch.codigoLibro);
printf("%s\n", regControl->bloqueLibrosPrestados[cont-2]);
}
I want to know how to add another string of 2 length next to the one that is 7 length. This codes are parts of a code that reads from a file until it reaches EOF, that's why I used a counter which is "cont".
You have a char**.
Suppose a. Allocate some memory to a.
a= malloc(sizeof(char*)*10);
if( a == NULL)
{
fprintf(stderr,"%s","error in malloc");
exit(1);
}
Now for each of the position of a you do the same thing only this time it is for char.
a[i]= malloc(sizeof(char)*100);
if( a[i] == NULL)
{
//...
}
Free them when done.
free(a[i]); //for each i.
free(a);
a=NULL;
Now this is 2 dimension
Now I don't know when you need more than this. This can always be extended.
char *** aa; But it is not needed. {read this}
If you need it then you should think over your data representation.
Theoretical idea for N dimensional strings
For n dimensional you can do this:-
char **...n...** complicated= malloc(sizeof(char**...n...>**)*N1);
// malloc check
for(int i=0;i<N1;i++)
complicated[i]= malloc(sizeof(char**...(n-1)...**)*N2);
...

How to properly copy char array to char array?

I am quite a newbie on C and am trying to get a C routine working.
const char *filenames[entry_count];
for (i = 0; i < entry_count; i++) {
char filename_inzip[256];
unz_file_info file_info;
err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip,
sizeof(filename_inzip), NULL, 0, NULL, 0);
//This doesn't work. My array gets filled with the last entry over and over.
filenames[i] = filename_inzip; //Option 1
//Here I get SIGSEV errors, or gibberish in output when debugging values
strcpy(filenames[i], filename_inzip); //Option 2
}
I guess the first assignment doesn't work because it just points to the same temporary memory address of the char[256] in the loop.
The second option doesn't work I think because I haven't use malloc or similar.
How would I get a properly filled array?
You're correct that you need to allocate memory in the second option.
filenames[i] = strdup(filename_inzip);
is the easiest way of doing this.
strdup is a Posix function rather than standard C. If it isn't available for you
filenames[i] = malloc(strlen(filename_inzip)+1);
if (filenames[i] != NULL) {
strcpy(filenames[i], filename_inzip);
}
does an equivalent job
Note that you'll also have to call free for each array element you allocate later in your program.

Reading text file into array using Scanner: Null Pointer Exception

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!

c string array comparison

Working in C, I'm filling an array with char* return values from a function
char* files[4][12];
int i = 0;
for (;;)
{
char* file = get_value();
strcpy(files[i],file);
i++;
if (i > 4 || external_condition)
break;
}
// When I break out of
// my for loop the following
// code executes
for (i = 0; i < 5; i++)
{
if (files[i] != NULL)
manipulate(files[i]);
}
My problem is that if I break out of the first for loop without assigning values to all elements of files, my comparison in the second for loop fails. If only files[0] and files[1] have content, the loop processes files[2],file[3] and files[4] anyway.
files is declared as an "array of arrays of pointers to char". Or if you prefer, as a two-dimensional array of pointers to char.
So files[i] is of type "array of pointers to char" but you use it as just a "pointer to char". That is wrong.
That said, it is not clear what you want to do... maybe just:
char files[5][13];
will make more sense. 13 because you likely need 13 char strings (8.3 are 8+3+1=12 plus 1 for the ending NUL), and you seem to use 5 of them. Then initialize them to zero:
memset(files, 0, sizeof(files));
And use the check:
if (files[i][0])
to check if a text is initialized.
char* files[4][12] is a 2D array of char *, not char. Perhaps you meant your code to be as follows... I suggest you listen to what others have said. I'm merely posting a shortened version that still works.
char files[5][12] = { { 0 } };
int i = 0;
do {
strcpy(files[i], get_value());
} while (++i <= 4 && !external_condition);
while (i) {
manipulate(files[--i]);
}

Resources