i have been trying to write the order in which the tree is traversed, to a .txt file in C. Instead of using arrays, i'm using my own data type vector to store the node values of the tree. I then try to create a character array from the items in the vector. This process goes as expected, however when i print the char array to the screen, it prints 5 random character in the beginning. I'm sure enough that the problem isn't in the vector but elsewhere because when i try to print the characters inside the loop, it doesn't print any unexpected characters to the screen (please see image below). Help in spotting the bug will be highly appreciated.
NODE* char_tree = optimised_tree(); // First Node of the tree
vector* tree_items = new_vector();
parse_tree(char_tree, tree_items); // parses the tree and add nodes to vector
int len = vec_size(tree_items); // size of the vector
char xs[len + 2];
char x[2];
for (int i = 0; i < len; ++i)
{
int o = vec_get(tree_items, i); // item at index i in vector tree_items
printf("%c ", o);
x[0] = (char)o;
x[1] = '\0';
strcat(xs, x);
}
xs[len] = '\n';
xs[len + 1] = '\0';
printf("\n-> %sSIZE %lu\n", xs, sizeof(xs));
The problem is that you use the variable xs without initializing it! The code:
char xs[len + 2];
declares a character array but does not assign anything to it. So, you have a character array with arbitrary (= 'random') content.
To solve your problem, just initialize xs to an empty string, either when you declare it (see note below), or (better, IMHO) with code like the following before the start of the for loop:
strcpy(xs, "");
Note: You cannot use normal initializer syntax on variable length arrays! So, code like this will not work:
char xs[len + 2] = ""; // Cannot initialize VLA
but you could do this:
char xs[len + 2]; xs[0] = 0;
Related
Newbie C programmer (experienced in other high level languages) and I'm still struggling to get used to arrays, pointers vs strings etc.
This project is recreating something I did in python. I am storing a character set (7 lines high by 6 wide) in an array. The array is multi-dimensional to store all the lines of all the characters referenced by their corresponding ascii code - array structure: font[ascii_code][line]. See code below for clarity.
The main loop will read one character from the message, look up it's corresponding ascii code in the font array and write out a column at a time to another array which is sort of a matrix of all screen positions. That matrix array then gets written to the screen with curses. Then we shift all cols of the matrix to the left and loop again. This effectively creating a leftward scroll text. Once we finish all 6 cols of a character from the font array we increment the message position, get the next message character and loop again.
My issues (I am sure because I am still learning the intricate ways of c programming):
I get an incredible amount of 'integer from pointer without a cast' errors which I believe is to do with referencing a string rather than a pointer to a string, but I'm struggling to understand this. I have been putting & in front of array references - it seems to sometimes work but not others.
I also don't understand why a declaration like
char cur_char = ' ';
works fine but this does not:
char msg = "This is a message";
but this does:
char msg[] = "This is a message";
I read that I should use single quotes for a single character and double quotes for a string. I understand that chars are really arrays of ascii values but why it's necessary to declare with the brackets I don't really understand.
Again calling the curses function like this:
mvaddch(1, 74, " ");
gets me an 'integer from pointer' error. I was hoping to draw a space at row 1 col 74. If this function expects a pointer rather than a string, does that mean it's necessary to store a space in a char and then pass the pointer of that char to the function? I'm trying to figure out the proper approach here.
Finally, I am just after some guidance from more experienced c programmers as to a logical approach to this. Maybe storing all these strings in a large array is not the way to do it. Is it possible (practical) to put this character set in memory and reference it that way?
Any suggestions, tips and advice, gratefully and humbly accepted. Appreciate your eyeballs and I am determined to master this language!
Bonus round
Originally I tried loading in my character set array from a function in a header file so I wouldn't have all these ugly data lines in the main c file. Gave up because I couldn't pass arrays back as a function return value. I am sure there's a better way. How would you split it out?
Here's the code:
Still getting errors on:
mvaddch(l, m, scr_matrix[l][m]); // makes integer from pointer error;
strcpy(scr_matrix[l][m], &scr_matrix[l][m + 1]); // incompatible pointer type
Here is a test version of my code. Put comments in for clarity.
#include <curses.h>
#include <unistd.h> // For sleep()
#include <string.h> // For strlen()
#include <stdlib.h> // For malloc()
int main(int argc, char* argv[])
{
// Let's initialise constants and set some configs
char msg[] = "XYZ";
int msg_length;
int i, j, k, l, m;
int msg_pos = 0;
int char_pos = 0;
char cur_char = ' ';
// Array to make a matrix that we will draw to screen with curses
char scr_matrix[7][76][2]; // Our lines (7) and cols (76) positions in an array
// Lets just initalise all the array elements to contain spaces
for (i = 0; i < 14; i++) {
for (j = 0; j < 75; j++) {
strcpy(scr_matrix[i][j], " "); //Have to use strcpy because can't set element
}
}
// char font array to hold our char set
char font2[100][7][7]; // 100 chars, 7 tall by 6 wide (+ /0 makes 7)
// Set array elements - first element correspond to char ascii code
// glyphs are 7 lines tall by 6 wide
// Use strcpy because cannot directly set elements?
strcpy(font2[88][0], "## ##");
strcpy(font2[88][1], "## ##");
strcpy(font2[88][2], " #### ");
strcpy(font2[88][3], " ## ");
strcpy(font2[88][4], " #### ");
strcpy(font2[88][5], "## ##");
strcpy(font2[88][6], "## ##");
strcpy(font2[89][0], "## ##");
strcpy(font2[89][1], "## ##");
strcpy(font2[89][2], " #### ");
strcpy(font2[89][3], " #### ");
strcpy(font2[89][4], " ## ");
strcpy(font2[89][5], " ## ");
strcpy(font2[89][6], " ## ");
strcpy(font2[90][0], "######");
strcpy(font2[90][1], "######");
strcpy(font2[90][2], " ## ");
strcpy(font2[90][3], " ## ");
strcpy(font2[90][4], " ## ");
strcpy(font2[90][5], "######");
strcpy(font2[90][6], "######");
// Get msg length
msg_length = strlen(msg);
// Initialize screen for curses
initscr();
// Hide the cursor with curses
curs_set(0);
for (i = 0; i < msg_length; i++) {
cur_char = msg[msg_pos]; // keep track of which char from msg we are working on
// Loop for 6 cols - 6 for glyph width
for (j = 0; j < 7; j++) {
clear(); // Clear the screen with curses
// Loop for 7 lines - writing 1 char of the glyph to the matrix
for (k = 0; k < 7; k++) {
// cpy the character from font array into the matrix array
strcpy(scr_matrix[k][74], &font2[cur_char][k][j]);
}
// Now add all matrix positions to the screen with curses mvaddch
// Loops through all positions in scroll area
for (l = 0; l < 7; l++) {
for (m = 0; m < 75; m++) {
mvaddch(l, m, scr_matrix[l][m]); // add to screen with curses
// now shift this character in the matrix over by -1 col so it shifts left
strcpy(scr_matrix[l][m], &scr_matrix[l][m + 1]);
}
}
// Now draw the screen as built by curses with mvaddch
refresh();
// Wait a bit - pause for timing purpose
usleep(80000);
} // Back to top of loop for the next col
// Finished the glyph so add a col of spaces for kerning between letters
for (l = 0; l < 7; l++) {
mvaddch(l, 74, " ");
refresh();
usleep(80000);
}
msg_pos++;
}
// Clean up our curses screen
endwin();
return 0;
}
The problem comes from the fact that C was basically crated without type safety and types checks were added later on, when some convinience syntax was alredy in place.
The convinience feature is that the name of an array can be used as a pointer to the first element if the indexing is left away.
char array[10];
char two_dim_array[10][20];
char *charpointer;
charpointer = array; /* leaving the index away, so pointer to first element */
charpointer = &array[0]; /* basically the same */
charpointer = two_dim_array[3]; /* is short for */
charpointer = &two_dim_array[3][0]; /* this */
But if you use an array variable without index in sizeof or the address operator the compiler still knows it's an array.
char array[10];
char two_dim_array[10][20];
int size;
char *charpointer;
size = sizeof(array); /* 10 */
size = sizeof(two_dim_array[3]); /* 20 */
charpointer = &two_dim_array[10]; /* wrong pointer type, address of array of 20 char */
To your Errors from the compiler:
mvaddch(l, m, scr_matrix[l][m]); // makes integer from pointer error;
As scr_matrix is declared as char scr_matrix[7][76][2];
scr_matrix[l][m] is a pointer to the fist byte of the string, of the lowest level array. The Compiler complains as mvaddch expects the integer code of the character scr_matrix[l][m][0] would be fine.
strcpy(scr_matrix[l][m], &scr_matrix[l][m + 1]); // incompatible pointer type
Here the second parameter is
&scr_matrix[l][m + 1] the address of an array of 2 charaters.
Expected is a pointer to a character scr_matrix[l][m + 1] would be fine.
explanation
char cur_char = ' ';
works fine becuase '<char>' is a single (8 bit) character literal. char is a data type that stores an 8-bit character
This doesnt work
char msg = "This is a message";
because char only holds one character.
Sidebar: character strings in c:-
a character string in c is an contiguous array of 8-bit chars follows by a byte of 0
so this "Hello" is stored in memory as
x48x65x6cx6cx6fx00
H e l l o
OK so what this
char msg[] = "Hello";
does is creates a 6 (note the +1 for the 0) byte array on the stack and loads the letters Hello into it and adds the 0.
this does something quite different
char *msg = "Hello";
this creates a 6 byte character array as a literal (usualy in the code segment) and the creates a pointer of the stack (called msg) and sets it to point at that literal
Hope this helps.
I have not programmed in C in a long time. I am forgetting some fundamentals due to programming in JavaScript for so long, and would like some guidance.
I am making a program to display text on a LED matrix. Each character is represented by a series of 8 digit binary codes which represent columns of pixels. The idea is that for each character in a phrase, the code will fetch the relevant codes for that character and push them into a larger array.
The issue I am having is with passing / indexing an array filled with sub-arrays. When I try to run this code I get the error "invalid types 'int[int]' for array subscript".
How can I achieve the functionality I intend to? Here is my code.
int A[] = {01111111,10010000,10010000,10010000,01111111,00000000};
int B[] = {11111111,10010001,10010001,10010001,01101110,00000000};
int Space[] = {00000000,00000000};
char alphabet[] = "AB ";
int alphabetB[3] = {A,B,Space};
char phrase[] = "AB BAA";
int getLetterIndex(char letter,char alphabet[]){
for(int index; index < strlen(alphabet); index++){
if(alphabet[index] == letter){
return index;
}
}
}
int writePhrase(char phrase[],char alphabet[], int alphabetB[]){
int phraseB[]={};
int pos = 0;
for(int charIndex = 0; charIndex < strlen(phrase); charIndex++){
int index = getLetterIndex(letter,alphabet);
for(int colIndex = 0; colIndex < sizeof(alphabetB[index]); colIndex++){
phraseB[pos] = alphabetB[index][colIndex];
pos++;
}
}
return phraseB;
}
writePhrase(phrase,alphabet,alphabetB);
Thank you!
Problematic line in your code:
int A[] = {01111111,10010000,10010000,10010000,01111111,00000000};
Wrong type of array, int is 2 byte long. You probably want array of bytes. Octal and decimal constant for assign byte. Replace with char A[] = {0x7f, 0x90, 0x90, 0x7f, 0x00};
int alphabetB[3] = {A,B,Space};
alphabetB isn't two dimensional array. It is array of int. A is address of array A not array as whole object. It is same as expression &A[0] = address of first element. Replace as char* alphabetB[3] = {A,B,Space};
Function getLetterIndex don't return error indication if letter is not in alphabet.
int phraseB[]={};
C does not support arrays with a dynamic number of elements. You must define size of array, or initializer list. Also you can not create array as local variable. Local variables is allocated on the stack and it is released at end of the function. Btw function not return array, but address of phraseB on the stack
int index = getLetterIndex(letter,alphabet);
letter is not defined. Probably you wont pass char from phrase like int index = getLetterIndex(phrase[charIndex],alphabet);
Last problem is copy loop. alphabetB isn't two dimensional array. You can't do this assigment phraseB[pos] = alphabetB[index][colIndex];
Also here is posibility rewriting stack frame and program hang up.
Look here, how to do matrix control in C.
maxtrix control example
Im working on a project and I am stumped on this part.
I need to read words from stdin and place them in a char array and use an array of pointers to point to each word since they will be jagged. where numwords is an int read in representing the number of words.
char words[10000];
char *wordp[2000];
the problem is that I can only use the pointers to add the words.I can no longer use the [] to help.
*wordp = words; //set the first pointer to the beginning of the char array.
while (t < numwords){
scanf("%s", *(wordp + t)) //this is the part I dont know
wordp = words + charcounter; //charcounter is the num of chars in the prev word
t++;
}
for(int i = 0;words+i != '\n';i++){
charcounter++;
}
any help would be great I am so confused when it comes to pointers and arrays.
Your code will be much more manageable if you use an additional pointer
reference and increment that directly. In this way you won't have to do any
mental math. Additionally you need to be incrementing the reference before
reading in the next string, scanf doesn't move the pointer for you.
char buffer[10000];
char* words[200];
int number_of_words = 200;
int current_words_index = 0;
// This is what we are going to use to write to the buffer
char* current_buffer_prt = buffer;
// quick memset (as I don't remember if c does this for us)
for (int i = 0; i < 10000; i++)
buffer[i] = '\0';
while (current_words_index < number_of_words) {
// Store a pointer to the current word before doing anything to it
words[current_word_index] = current_buffer_ptr;
// Read the word into the buffer
scanf("%s", current_buffer_ptr);
// NOTE: The above line could also be written
// scanf("%s", words[current_word_index]);
// this is how we move the buffer to it's next empty position.
while (current_buffer_ptr != '\n')
current_buffer_ptr++;
// this ensures we don't overwrite the previous \n char
current_buffer_ptr++;
current_words_index += 1;
}
What you want to do is relatively straightforward. You've got an array of 10,000 chars for storage, and 2000 pointers. So to start with you'll want to assign the first pointer to the start of the array:
wordp[0] = &words[0];
In pointer form this is:
*(wordp + 0) = words + 0;
I've used the zeros to show how it relates to the arrays. In general, to set each pointer to each element:
*(wordp + i) == wordp[i]
words + i == &words[i]
So all you need to do is keep track of where you are in the pointer array, and as long as you've assigned correctly, the pointer array will keep track of the position in your char array.
new here, trying to learn a piece of C with the great help of you guys, this could be a basic questions here....sorry you have start from basic.
void main()
{
char* arr[3] = {"baba","tata","kaka"};
char* arr1[3] = {"baba1","tata1","kaka1"};
char* arr2[3] = {"baba2","tata2","kaka2"};
char** array_all[] = {arr,arr1,arr2};
printf("%s\n",*array_all[0]);
//please guide me how to access individual entity(as arr[1], arr1[2],arr3[1]) //from each array using array_all
}
I'm not sure if this is exactly what you were looking for.. but this is what I understand so far.
You are wanting to access the individual elements of array_all (the elements arr, arr1 and arr2)? If so then all you do is...
array_all[0][i];
Where i is the element that you want to access.
The reason for this is because the index operators ([ and ]) actually dereferences a pointer and offsets the pointer (as in adds it by some integer, i.e. you move down in memory) that you specify. I recommend reading up on pointer arithmetic if you have no clue what happens if you add a pointer by some integer.
For example:
int x[] = { 1, 2, 3 };
// writing x[i] is the same as *(x + i)
int i = 2; // the element you wish to access
*(x + i) = 4; // set the ith (3rd) element to 4
*(x + 1) = 43; // set the 2nd element to 43
// Therefore...
// x now stores these elements:
// 1, 43, 4
// proof: print out all the elements in the array
for(int i = 0; i < 3; ++i)
{
printf("x[%i]=%i\n", i, x[i]);
}
Also, writing x[0] is the same as writing *x, since the array name actually points to the first element of the array.
OH and one thing, main should actually return an integer result. This is mainly used for error checking in your program, 0 usually means no error occurred and every other error-code (number other than 0) is some specific error related to your program, that you can choose.
i.e.
int main()
{
// e.g. for an error code
/*
if(someErrorOccured)
{
return SOME_ERROR_OCCURED_RETURN_VALUE;
}
*/
return 0; // this is at the end of the function, 0 means no error occured
}
change your printf statement line with this..
printf("%s\n",array_all[i][j]);
In place of i keep your array number and in place of k give your required element number. It works.
I am new to C, so forgive me if this question is trivial. I am trying to reverse a string, in
my case the letters a,b,c,d. I place the characters in a char* array, and declare a buffer
which will hold the characters in the opposite order, d,c,b,a. I achieve this result using
pointer arithmetic, but to my understanding each element in a char* array is 4 bytes, so when I do the following: buffer[i] = *(char**)letters + 4; I am supposed to be pointing at the
second element in the array. Instead of pointing to the second element, it points to the third. After further examination I figured that if I increment the base pointer by two
each time I would get the desired results. Does this mean that each element in the array
is two bytes instead of 4? Here is the rest of my code:
#include <stdio.h>
int main(void)
{
char *letters[] = {"a","b","c","d"};
char *buffer[4];
int i, add = 6;
for( i = 0 ; i < 4 ; i++ )
{
buffer[i] = *(char**)letters + add;
add -= 2;
}
printf("The alphabet: ");
for(i = 0; i < 4; i++)
{
printf("%s",letters[i]);
}
printf("\n");
printf("The alphabet in reverse: ");
for(i = 0; i < 4; i++)
{
printf("%s",buffer[i]);
}
printf("\n");
}
You're not making an array of characters: you're making an array of character strings -- i.e., an array of pointers to arrays of characters. I am not going to rewrite the whole program for you of course, but I'll start out with two alternative possible correct declarations for your main data structure:
char letters[] = {'a','b','c','d, 0};
char * letters = "abcd";
Either of these declares an array of five characters: a, b, c, d followed by 0, the traditional ending for a character string in C.
Another thing: rather than making assumptions about the size of things, use the language to tell you. For instance:
char *my_array[] = { "foo" , "bar" , "baz" , "bat" , } ;
// the size of an element of my_array
size_t my_array_element_size = sizeof(my_array[0]) ;
size_t alt_element_size = size(*my_array) ; // arrays are pointers under the hood
// the number of elements in my_array
size_t my_array_element_cnt = sizeof(my_array) / sizeof(*myarray ;
// the size of a char
size_t char_size = sizeof(*(my_array[0])) ; // size of a char
Another thing: understand your data structures (as noted above). You talk about chars, but your data structures are talking about strings. Your declarations:
char *letters[] = {"a","b","c","d"};
char *buffer[4];
get parsed as follows:
letters is an array of pointers to char (which happen to be nul-terminated C-style strings), and it's initialized with 4 elements.
Like letters, buffer is an array of 4 pointers to char, but uninitialized.
You are not actually dealing individual chars anywhere, even in the printf() statements: the %s specifier says the argument is a nul-terminated string. Rather, you're dealing with strings (aka pointers to char) and arrays of the same.
An easier way:
#include <stdio.h>
int main(void)
{
char *letters[] = { "a" , "b" , "c" , "d" , } ;
size_t letter_cnt = size(letters)/sizeof(*letters) ;
char *buffer[sizeof(letters)/sizeof(*letters)] ;
for ( int i=0 , j=letter_cnt ; i < letter_cnt ; ++i )
{
buffer[--j] = letters[i] ;
}
printf("The alphabet: ");
for( int i = 0 ; i < letter_cnt ; ++i )
{
printf("%s",letters[i]);
}
printf("\n");
printf("The alphabet in reverse: ");
for( int i=0 ; i < letter_cnt ; i++ )
{
printf("%s",buffer[i]);
}
printf("\n");
}
BTW, is this homework?
This is a case of operator precedence. When you use buffer[i] = *(char**)letters + add;, the * before the cast is performed before the +, making this code equivalent to (*(char**)letters) + add;. The first part is equivalent to the address of the first element in your array, the string "a". Since using string constant automatically adds a null byte, this points to 'a\0'. It happens that the compiler placed all four strings immediately after each other in memory, so if you go past the end of that string you flow into the next. When you add to the pointer, you are moving through this character array: 'a\0b\0c\0d\0'. Notice that each character is 2 bytes after the last. Since this is only true because the compiler placed the 4 strings directly after each other, you should never depend on it (it won't even work if you tried to re-reverse your other string). Instead, you need to put in parentheses to make sure the addition happens before the dereference, and use the 4 byte pointer size. (Of course, as pointed out by Nicholas, you shouldn't assume the size of anything. Use sizeof to get the size of a pointer instead.)
buffer[i] = *((char**)letters + add);
char *letters[] = {"a","b","c","d"};
I think you didn't get the pointer arithmetic correctly. letters is an array of pointers and when incremented by 1 makes to go to next row.
letters + 1 ; // Go to starting location of 2 row, i.e., &"b"
char *letters[] = { "abc" , "def" } ;
(letters + 1) ; // Point to the second row's first element, i.e., &"d"
*((*letters) + 1) ; // Get the second element of the first row. i.e., "b"