I'm trying to read a text file called "olaola.dict", some sort of a dictionary, that currently holds 10 words each with 5 letters and store the words into an array of strings. I'm using a char** pointer that points to an array of pointers in which each pointer points to a word from the dictionary.
So far, I've developed this code. It is printing the last 7 words correctly, but not the first three. The code is the following:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ROW 10 /* 10 words */
#define COL 6 /* 5 letters in each word + Null terminator*/
int main(void) {
int i, j;
FILE *fp = NULL;
char **ptr = NULL;
ptr = (char**)malloc(ROW * sizeof(char*));
fp = fopen("olaola.dict","r");
for (i=0 ; i < 15; i++) {
if ((ptr[i] = malloc(sizeof(char) * COL)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
fscanf(fp, "%s", ptr[i]);
}
for(i = 0; i < ROW; i++){
printf("Word %d:%s\n", i+1,ptr[i]);
}
for (i=0 ; i < ROW; i++)
free(ptr[i]);
free(ptr);
fclose(fp);
return 0;
}
/*
ptr[] 0 1 2 3 4 5 6
+--------+ +---+---+---+---+---+---+---+
| --|------->| w | o | r | d | 0 | 0 |\0 |
+--------+ +---+---+---+---+---+---+---+
| --|------->| w | o | r | d | 0 | 1 |\0 |
+--------+ +---+---+---+---+---+---+---+
| --|------->| w | o | r | d | 0 | 2 |\0 |
+--------+ +---+---+---+---+---+---+---+
| --|------->| w | o | r | d | 0 | 3 |\0 |
+--------+ +---+---+---+---+---+---+---+
| --|------->| w | o | r | d | 0 | 4 |\0 |
+--------+ +---+---+---+---+---+---+---+
*/
The output is:
Word 1:[p:�
Word 2:0[p:�
Word 3:P[p:�
Word 4:Carlo
Word 5:Andre
Word 6:MESSI
Word 7:Arroz
Word 8:Doces
Word 9:Carro
Word 10:Tevez
Here is also the text file olaola.dict
lista
Sabes ontem Carlo
Andre
MESSI
Arroz Doces Carro Tevez
As you can see, there is no specific position for the words to be.
What would be the correct way to solve this problem?
(In another note, would it be wiser and more efficient to use a 2D array, even though the dictionary can have like 5k words ?)
I noticed that the first for loop goes from zero to 14 instead of from zero to 9. This means that the code writes beyond the boundaries of the array. I assume that this writes to the memory being allocated for the first 3 words and this is the reason why you see the wrong values for these words. Correct the for loop and see if this solves the issue.
you problem is in this line
for (i=0 ; i < 15; i++) {
it's supposed to be:
for (i=0 ; i < ROW; i++)
because you should allocate till ptr[9], but you are allocating till ptr[14] which will produce undefined behavior as the size of the array = 10
I am trying to understand code snippets in
free a double pointer
and
Why use double pointer? or Why use pointers to pointers?
I want to understand the difference between the following. Both snippets are from the above urls
int** pt;
pt = (int*) malloc(sizeof(int)*10);
and
*pt = (int*) malloc(sizeof(int)*10);
Could you elaborate with some examples and drawing
First of all, the code snippet is bad for several reasons - the first is casting the result of malloc to the wrong type, and is using the wrong type to compute the amount of memory. Fixing the cast and type issues, we have:
int **pt;
pt = malloc( sizeof *pt * 10 ); // allocate space for 10 int *
*pt = malloc( sizeof **pt * 10 ); // allocate space for 10 int
After executing the first line, you have the following:
int ** int *
+---+ +---+
pt: | | --------------->| | pt[0]
+---+ +---+
| | pt[1]
+---+
| | pt[2]
+---+
...
+---+
| | pt[9]
+---+
You've set aside space for 10 int * objects, and pt points to the first of them.
The next line
*pt = malloc( sizeof **pt * 10 ); // allocate space for 10 int
allocates space for 10 int objects, and sets pt[0] to point to them:
int ** int * int
+---+ +---+ +---+
pt: | | --------------->| | pt[0] -------->| | pt[0][0]
+---+ +---+ +---+
| | pt[1] | | pt[0][1]
+---+ +---+
| | pt[2] | | pt[0][2]
+---+ +---+
... ...
+---+ +---+
| | pt[9] | | pt[0][9]
+---+ +---+
This illustrates one way of allocating a "jagged" array; you can still index it as pt[i][j], but unlike a true 2D array the rows are not adjacent in memory, and each row may be a different length. You'd normally write that as
pt = malloc( sizeof *pt * ROWS );
if ( pt )
{
for ( size_t r = 0; r < ROWS; r++ )
{
pt[r] = malloc( sizeof *pt[r] * COLS );
}
}
When that's all done, you have something like this:
int ** int * int
+---+ +---+ +---+---+ +---+
pt: | | ---------> | | pt[0] --------> | | | ... | | pt[0][0] - pt[0][COLS-1]
+---+ +---+ +---+---+ +---+
| | pt[1] ------+
+---+ | +---+---+ +---+
| | pt[2] ---+ +-> | | | ... | | pt[1][0] - pt[1][COLS-1]
+---+ | +---+---+ +---+
... |
| +---+---+ +---+
+----> | | | ... | | pt[2][0] - pt[2][COLS-1]
+---+---+ +---+
The following is wrong, compiler should complain about types:
int** pt;
pt = (int*) malloc(sizeof(int)*10);
This is also wrong for another reason (here pt does not actually point to anything usable):
int** pt;
*pt = (int*) malloc(sizeof(int)*10);
A pointer to T is a variable of type T * that may contain address of some memory that may contains elements of type T:
+------+
| | pointer to T
+------+
|
v
+-------------+-------------+-------------+
| | | | elements of type T
+-------------+-------------+-------------+
For example, in C, to obtain what is drawn, you can write:
int *pi;
pi = malloc(sizeof(int)*3);
If you have a pointer to pointer to T then then diagram could be something like:
+------+
| | pointer to pointer to T
+------+
|
v
+------+------+------+
| | | | pointers to T
+------+------+------+
| | | +-------------+-------------+-------------+
| | +---->| | | | elements of type T
| | +-------------+-------------+-------------+
| | +-------------+-------------+
| +---->| | | elements of type T
| +-------------+-------------+
|
v
+-------------+-------------+-------------+-------------+
| | | | | elements of type T
+-------------+-------------+-------------+-------------+
and the code could be:
int **ppi;
ppi = malloc(sizeof(int *)*3);
ppi[0] = malloc(sizeof(int)*3);
ppi[1] = malloc(sizeof(int)*2);
ppi[2] = malloc(sizeof(int)*4);
Of course, malloc could fail and return value should be tested against failure.
Using the casting you helped the compiler to find an error in this code snippet
int** pt;
pt = (int*) malloc(sizeof(int)*10);
For example the error message can look like
error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
pt = (int*) malloc(sizeof(int)*10);
^
Without the casting the compiler could accept this evidently invalid code because the return type of the function malloc is void * and a pointer of the type void * may be assigned to a pointer to object of any other type.
That is in the right side of the assignment the evaluated expression has the type int * while in the left side of the assignment there is an object of the type int ** and there is no implicit conversion from the type int * to the type int **.
This code snippet
int** pt;
*pt = (int*) malloc(sizeof(int)*10);
is invalid by another reason. The pointer pt is not initialized by a valid address of an object. It has either indeterminate value if the pointer has automatic storage duration or NULL if the pointer has static storage duration. In any case its dereferencing results in undefined behavior.
So it would be correctly to write
int* pt;
^^^^^^^
pt = (int*) malloc(sizeof(int)*10);
However this construction
int** pt;
//...
*pt = (int*) malloc(sizeof(int)*10);
can be made valid in some context.
Let's assume that you declared a pointer
int *pt;
and want to initialize it in a function. In this case you have to pass the pointer to the function by reference. Otherwise the function will deal with a copy of the pointer and in this case the original pointer will not be assigned in the function.
So the corresponding code snippet can look as it is shown in the demonstrative program
#include <stdlib.h>
#include <stdio.h>
size_t f( int **pt )
{
const size_t N = 10;
*pt = (int*) malloc( sizeof( int ) * N );
if ( *pt )
{
int value = 0;
for ( size_t i = 0; i < N; i++ ) ( *pt )[i] = value++;
}
return *pt == NULL ? 0 : N;
}
int main( void )
{
int *pt;
size_t n = f( &pt );
if ( n )
{
for ( size_t i = 0; i < n; i++ ) printf( "%d ", pt[i] );
putchar( '\n' );
}
free( pt );
}
The program output is
0 1 2 3 4 5 6 7 8 9
struct number {char digits[11];};
The following method removes leading zeroes from (*a).digits
void remove_zero(struct number *a);
Example: (*a).digits 000013204 ---> 13204
My approach is to define a variable b equals to (*a).digits, start seaching for the first non-zero number in b, then replace (*a).digits with the rest of b. However, I am having trouble implementing the code
void remove_zero(struct number *a) {
char b = (*a).digits;
while (b){ // <--- (b) indicates that it hasnt reached the terminator,right?
if (b != '0')
{ //<-- here is where to replace (*a).digits with the rest of b, but how to?
break;
}
}
}
So you have an array that contains e.g.
+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 1 | 3 | 2 | 0 | 4 | \0| |
+---+---+---+---+---+---+---+---+---+---+---+
And you want it to contain
+---+---+---+---+---+---+---+---+---+---+---+
| 1 | 3 | 2 | 0 | 4 | \0| | | | | |
+---+---+---+---+---+---+---+---+---+---+---+
From the "images" above, it should be pretty clear that this can be done using a simple movement of the data.
So one solution is to find the first non-zero character, and move from that to the beginning of the array.
In general it's clearer to deference a pointer to a struct and access its attributes using the -> operator, e.g. rather than
char b = (*a).digits;
do this
char *b = a->digits;
Note that digits is an array of chars, so b needs to be an array of chars, or a pointer to a char as shown here.
So:
void remove_zero(struct number *a)
{
char *b = a->digits;
char *end = a->digits + sizeof a->digits - 1;
while (b < end && *b == '0')
b++;
if (b != a->digits)
{
size_t n = end - b;
memmove(a->digits, b, n);
a->digits[n] = '\0';
}
}
For my assignment one of the things I have to do in my program is dynamically allocate a 2D array.
I can't figure out how to do it or why.
This is what I have now.
size = atoi(argv[1]);
int Pond[size][size];
int i, j;
for(i = 0; i < size; i ++){
for(j = 0; j < size; j++){
Pond[i][j]=0;
}
}
I found a answer to do it this way but I can't figure out how to access each column or row.
int **Pond;
Pond = (int**)malloc(size * sizeof(int*));
for (i = 0; i < size; i++) {
Pond[i] = (int *) malloc(size * sizeof(int));
Correct use of C's powerful array type syntax looks like this:
int (*Pond)[size] = malloc(size * sizeof(*Pond));
That's it for the allocation. After that, the elements in Pond can simply be accessed like this:
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
Pond[y][x] = 0;
}
}
And of course the deallocation:
free(Pond);
It doesn't get simpler.
The [] operator works on pointers pretty much the same way it works on array expressions, so you'd use Pond[i][j] to access a particular element regardless of how you allocate (unless you allocated it as a 1D array as dom0 shows).
If the number of rows and columns are known at compile time, this is the easiest:
#define M ... // rows
#define N ... // columns
int (*Pond)[N] = malloc ( sizeof *Pond * M);
...
Pond[i][j] = x;
...
free( Pond );
The type of the variable Pond is "pointer to N-element array of int". The type of the expression *Pond is "N-element array of int". So sizeof *Pond gives us the number of bytes in N-element array of int; we multiply this by M to get the total number of bytes required for the array.
Since a[i] is evaluated as *(a + i), the [] operator works the same way on a pointer expression as it does on an array expression1; that is, you could use Pond[i][j] here as you would for a regular 2D array.
If the number of rows and columns are not known until run time, but you're using a C99 compiler or a C2011 compiler that supports variable length arrays, it's pretty much the same:
size_t n, m;
/**
* get values of n and m
*/
int (*Pond)[n] = malloc( sizeof *Pond * m );
...
Pond[i][j] = x;
...
free( Pond );
Same deal as above, it's just that m and n aren't known until runtime. In both of these cases, the dynamically-allocated arrays are contiguous (all rows are adjacent in memory).
+---+
Pond: | | ---+
+---+ |
... |
+---+ |
Pond[0][0]: | | <--+
+---+
Pond[0][1]: | |
+---+
...
+---+
Pond[0][n-1]: | |
+---+
Pond[1][0]: | |
+---+
Pond[1][1]: | |
+---+
...
+---+
Pond[m-1][0]: | |
+---+
Pond[m-1][1]: | |
+---+
...
+---+
Pond[m-1][n-1]: | |
+---+
If the number of rows and columns aren't known until runtime, and you're using a compiler that does not support VLAs, you have two choices depending on whether you want the arrays to be contiguous or not.
If the array doesn't have to be contiguous, you can use a two-step allocation approach:
size_t n, m;
/**
* get values for n and m
*/
int **Pond = malloc( sizeof *Pond * m ); // allocate m rows of pointer to int
if ( Pond )
{
for ( size_t i = 0; i < m; i++ )
{
Pond[i] = malloc( sizeof *Pond[i] * n ); // allocate n columns of int for each row
}
}
In this case, Pond is a pointer to pointer to int; it will wind up pointing to what is effectively a 1D array of pointers to int; each of those pointers will point to a 1D array of int, sort of like the following:
+---+
Pond: | | ---+
+---+ |
|
+------+
|
V
+---+
Pond[0]: | | ------------+
+---+ |
Pond[1]: | | ---------+ |
+---+ | |
Pond[2]: | | | |
+---+ | |
... | |
+---+ | |
Pond[m-1]: | | | |
+---+ | |
| |
+---+ | |
Pond[0][0]: | | <--------|--+
+---+ |
Pond[0][1]: | | |
+---+ |
... |
+---+ |
Pond[0][n-1]: | | |
+---+ |
|
+---+ |
Pond[1][0]: | | <--------+
+---+
Pond[1][1]: | |
+---+
...
+---+
Pond[1][n-1]: | |
+---+
But because Pond[i][j] is evaluated as *(*(Pond + i) + j), it all still works.
Note that since this was a two-step allocation process, deallocation also requires two steps:
for ( size_t i = 0; i < m; i++ )
free( Pond[i] );
free( Pond );
If the array does need to be contiguous, then you'll have to allocate the memory as a 1D array and compute your indexes manually:
int *Pond = malloc( sizeof *Pond * m * n );
...
Pond[ i * m + j ] = x;
...
free( Pond );
1. Under most circumstances, an array expression will be converted or "decay" to a pointer expression, so the subscript is actually working on a pointer expression either way.
Playing with pointers in C is fun (not really).
I have several arrays of strings I want to declare in an easy way, preferably something like:
arrayOfStrings1 = {"word1", "word2", etc. };
arrayOfStrings2 = {"anotherword1", "anotherword2", etc. };
arrayOfStrings3 = etc.
etc.
Something similar to a translation array (but not quite), so I want to be able to swap between these during runtime. For that I want a pointer pointerToArrayOfStrings that I can swap like:
pointerToArrayOfStrings = arrayOfStrings1;
doStuff();
pointerToArrayOfStrings = arrayOfStrings2;
doSomeOtherStuff();
In my naive understanding of arrays of strings and pointers to these, this is what I tried:
// Danish transforms
const unsigned char* da_DK[] = {"b","bb","c","c","cc","d","dd","e","f","ff","g","gg","h","hh","j","j","jj","k","k","kk","l","l","l","l","ll","m","mm","n","n","nn","p","pp","r","r","r","rr","s","s","s","ss","t","t","tt","v","v","vv","æ"};
// British english transforms
const unsigned char* en_GB[] = {"a","a","a","a","a","a","a","a","a","a","a","a","a","age","ai","aj","ay","b","cial","cian","cian","dj","dsj","ea","ee","ege","ei","ei","eigh","eigh","f","f","f","g","g","gs","i","i","i","j","j","k","ks","kw","l","m","n","n","o","r","s","s","sd","sdr","sion","sion","sj","sj","tial","tion","tion","tj","u","u","u","u","w","ye","ye","z"};
// More languages....
const unsigned char** laguageStrings;
// Assign language
if (streq(language, "da-DK")){
laguageStrings= da_DK;
}
else if (streq(language, "en-GB")){
laguageStrings= en_GB;
}
else
return 0;
}
Language is a char * containing the language "en-GB", "da-DK" etc., streq() is just a home brewed (somewhat faster than strcmp()) string comparison function.
Long story short, depending on compiler this approach may work, report compiler warnings or compile, but give unexpected results.
What would be the correct way to solve this problem?
There are two way of working with array of characters (strings) in C. They are as follows:
char a[ROW][COL];
char *b[ROW];
Pictorial representation is available as an inline comment in the code.
Based on how you want to represent the array of characters (strings), you can define pointer to that as follows
char (*ptr1)[COL] = a;
char **ptr2 = b;
They are fundamentally different types (in a subtle way) and so the pointers to them is also slightly different.
The following example demonstrates the different ways of working with strings in C and I hope it helps you in better understanding of array of characters (strings) in C.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ROW 5
#define COL 10
int main(void)
{
int i, j;
char a[ROW][COL] = {"string1", "string2", "string3", "string4", "string5"};
char *b[ROW];
/*
a[][]
0 1 2 3 4 5 6 7 8 9
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 1 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 2 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 3 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 4 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 5 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
*/
/* Now, lets work on b */
for (i=0 ; i<5; i++) {
if ((b[i] = malloc(sizeof(char) * COL)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
}
strcpy(b[0], "string1");
strcpy(b[1], "string2");
strcpy(b[2], "string3");
strcpy(b[3], "string4");
strcpy(b[4], "string5");
/*
b[] 0 1 2 3 4 5 6 7 8 9
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 1 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 2 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 3 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 4 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 5 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
*/
char (*ptr1)[COL] = a;
printf("Contents of first array \n");
for (i=0; i<ROW; i++)
printf("%s \n", *ptr1++);
char **ptr2 = b;
printf("Contents of second array \n");
for (i=0; i<ROW; i++)
printf("%s \n", ptr2[i]);
/* b should be free'd */
for (i=0 ; i<5; i++)
free(b[i]);
return 0;
}
What would be the correct way to solve this problem?
Well, the correct way would be to use a library specifically designed for dealing with multilanguage interfaces - for instance gettext.
Another way, though patchier, would be to use a hash table (also known as "dictionary" or "hash map" or "associative map" in other languages/technologies): Looking for a good hash table implementation in C
It's probably not the answer you were looking for, but you've asked the wrong question to the right problem.