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
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';
}
}
#include<stdio.h>
int main()
{
int arr[3] = {2, 3, 4};
char *p;
p = arr;
p = (char*)((int*)(p));
printf("%d, ", *p);
p = (int*)(p+1); //............statement 1
printf("%d", *p);
return 0;
}
In the above code, p = (int*)(p+1); means character pointer is type cast to integer pointer. So when we dereference p, It fetches the contents up to next int size (2 bytes or 4 bytes, depending on compiler). But when I am solving this question at www.indiabix.com, they have given
answer: 2, 0
How it can be 2, 0? As per my analysis,the answer should be 2, 3. Can anyone explain what should be the correct answer and why?
Let's say an int takes four bytes.
In a little endian system, the memory layout of arr looks like:
| | <--- one byte
+---+---+---+---+---+---+---+---+---+---+---+---+
| 2 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 4 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+---+---+---+---+
In a big endian system, the memory layout of arr looks like:
| | <--- one byte
+---+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 2 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 4 |
+---+---+---+---+---+---+---+---+---+---+---+---+
In a little endian system,
*p = 2;
*(p+1) = 0;
In a big endian system,
*p = 0;
*(p+1) = 0;
Depending on your platform, the output will be:
2 0
or
0 0
The code you have is perhaps meant to confuse. The line
p = (char*)((int*)(p));
doesn't do a damn thing.
The line
p = (int*)(p+1);
has the same effect as:
p = p+1;
If I have a multidimension pointer representation of a grid like so
char **p;
int w; // width (i.e. number of columns)
int h; // height (i.e. number of rows)
How do I go about creating a copy that is rotated by 90 degrees clockwise for NxM grid?
I've tried mallocing the height as the new width, and width as new height then transposing the values. Then I was going to finish by reversing the values of the row but I haven't managed to do this.
Actual transposition is moderately painful: you have to move every element from "where it is now" to "where it should be in the transposition". If you really do have a pointer p pointing to the first of M pointers, and each of those M pointers points to the first of N chars (used as if it's an array of size M of arrays of size N of chars):
+---+ +---+---+---+---+
p ---> | * | ----> | a | b | c | d |
+---+ +---+---+---+---+
| * | --
+---+ \ +---+---+---+---+
| * | -----------> | i | j | k | l |
+---+ \ +---+---+---+---+
\
\ +---+---+---+---+
--> | e | f | g | h |
+---+---+---+---+
then you need a new pointer (which I will call q) pointing to the first of N pointers, each of which points to the first of M chars (note: this is a different transposition than you asked for):
+---+ +---+---+---+
q ---> | * | -----> | a | e | i |
+---+ +---+---+---+
| * | --
+---+ \
| * |etc \ +---+---+---+
+---+ ---> | b | f | j |
| * |etc +---+---+---+
+---+
However, if you can live with relatively annoying subscript-writing and any cache miss effects on your runtime, you can simply access p[i][j] as p[j][i] or p[N-1-j][i], etc., to "pretend" that things are transposed. This might be easiest with some macros:
#define ORIENTATION_A(p, M, N, i, j) ((p)[i][j])
#define ORIENTATION_B(p, M, N, i, j) ((p)[(N)-1-(j)][i])
/* etc */
(note: none of the above is tested).
When using type char **, since the fixed-size solution is already posted I thought I would chime in with a dynamic, \0 terminated solution that works with various-sized arrays. If it is possible to terminate the arrays h and w can be omitted. This function can figure out the h and w. Of course it may be changed to support h and w, but the powers that be would rather I get back to work funding their empire rather than providing free help.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
/* rotate_array
w h
**p _______ **q ___
|A B C D|\0 ===> |E A|\0
h |E F G H|\0 ==> |F B|\0 w
NULL----- |G C|\0
|H D|\0
NULL-
*/
char **rotate_array(char **p) {
int w,h,hh;
char **q;
for (w=0;p[0][w];w++);
for (hh=0;p[hh];hh++);
if (!(q = malloc(w * sizeof q))) {
perror ("malloc");
exit (1);
} fprintf (stderr,"made it\n");
for (w=0;p[0][w];w++) {
if (!(q[w] = malloc(hh))) {
perror ("malloc");
exit (1);
} for (h=0;h<hh;h++) {
q[w][hh-h-1] = p[h][w];
} q[w][h]='\0';
} q[w]=NULL;
return q;
} void free_array(char **p) {
int h;
for (h=0;p[h];h++) {
free (p[h]);
} free (p);
}
// main
int main (int argc, char **argv) {
int h;
char *p[3]={"ABCD","EFGH",NULL};
char **q;
for (h=0;p[h];h++) {
printf ("%s\n",p[h]);
} printf ("\n");
q = rotate_array (p);
for (h=0;q[h];h++) {
printf ("%s\n",q[h]);
} free_array (q);
return 0;
}
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.