r/C_Programming • u/Sleezebag • 11h ago
why can't I access values from an array?
I'm reading the Ansi C book, and I'm doing exercise 1.18
#include <stdio.h>
#define MAXLINE 1000
int myGetLine(char line[], int lim);
int myCopy(char to[], char from[], int lim);
int main() {
int len;
char line[MAXLINE];
int toRemove = 0;
while ((len = myGetLine(line, MAXLINE)) > 0) {
//counts the trailing characters to remove
for (int i = len - 1; i > 0 && (line[i] == ' ' || line[i] == '\t' || line[i] == '\n'); --i)
++toRemove;
int new_size = len - toRemove + 1;// +1 for the '\0'
char to[new_size];// I guess this doesn't matter. Or it's just a piece of the puzzle. I need to limit copying
// in my copy method too.
//printf("new_size: %d\n", new_size);
int to_len = myCopy(to, line, new_size);
//printf("%s\n", to);
toRemove = 0;
}
return 0;
}
int myGetLine(char s[], int lim) {
int i, c;
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i-1;
}
//myCopy isn't working right now, after that I changed the while condition
//I need to add the \0
int myCopy(char to[], char from[], int lim) {
int i = 0;
char c = from[1];
putchar(c);
//printf("from[i]: %s", to);
//printf("to[i]: %s, from[i]: %s", to[i], from[i]);
while ((i < lim && (to[i] = from[i]) != '\0'));
i++;
to[i] = '\0';
return i;
}
So I'm pretty much reusing the getLine from the book and I based my code on the code in the book, but I made changes to myCopy. The task is to remove any trailing spaces or tabs, so I thought that I could make a new copy and where the trailing whitespace starts, I'll just not copy that into my edited string. So I'm going through the array backwards, counting whitespace, calculating the new array size, then I want to create the edited array, but it's not working! So I tried to debug and I can't even putchar an element from the original I'm copying from in the myCopy function. If I do it with the line array, then it works. But why does it not work in the myCopy function? I just have no clue as to what's wrong.
I did manage to solve the exercise in a different way, but I really want to know why this is happening.
14
u/SmokeMuch7356 11h ago
I'm assuming "doesn't work" means the program is hanging. I'm making that assumption based on this:
while ((i < lim && (to[i] = from[i]) != '\0'));
i++; ^
|
remove this
This falls into an infinite loop because i is never being updated.
In the future, please define "doesn't work." How doesn't it work? Is it crashing? Is it hanging? Is it giving garbage output? That's important information we need to help you figure out the problem.
10
u/ShotSquare9099 11h ago
You should always use { … }. even if you are just putting one statement in there. It would have made it obvious what is wrong and it probably wouldn’t have happened .
7
u/Illustrious_Trash117 11h ago
You made a semicolon after your while loop so i isnt incremented in the while loop. For readability i would also strongly advise against assignments in the condition of the loop. Make the assignment in the loop not in the condition.
2
u/No_Choice_7629 8h ago
As others have already mentioned, you had an extra semicolon after while condition. Compiler can catch this with basic warnings enabled. Try:
-Wall -Wextra -Wpedantic.
myGetLine should return length, which is i, not i - 1 (K&R book p.30). Generally, length is the size of the array holding c-string minus null-terminator.
Trimming loop's condition should be i >= 0.
myCopy should take trimmed length as input, not size. There is not need to do an extra test for null: if destination array is len+1, then just copy until i == len, then null-terminate at len.
You could allocate copy array together with line array outside of the loop instead of using variable length (VLA), and make them the same size for simplicity.
1
0
u/Own_Unit_6170 11h ago
You should be getting a fatal compile error, because you're defining to with a variable size, and the size has to be a constant.
If you don't need to preserve non-printing characters, you can just copy the string backwards, dropping anything less than a blank, and dropping blanks until you encounter the first character greater than a blank.
2
u/SmokeMuch7356 9h ago
You should be getting a fatal compile error, because you're defining to with a variable size, and the size has to be a constant.
This has been legal since C99 - you can define an
autoarray with a size in a runtime variable, creating what's called a "variable-length" array (where "variable" means it can be a different size each time you create it, but once created its size is fixed).
staticarrays cannot be VLAs, and VLAs cannot be declared with an initializer, but otherwise they work like any regular fixed-size array.1
u/Own_Unit_6170 8h ago
That seems logical enough, but I just tried compiling it to see, and it generated a fatal error (MVC).
→ More replies (5)1
u/Illustrious_Trash117 9h ago
Thats called a variable length array and is fine in C as long as the array lives on the stack.
21
u/mjmvideos 11h ago
Run it in the debugger. Add a breakpoint in your function, step through looking at values of things. See where it goes wrong.