Dynamic 2D array in C not reading first element











up vote
0
down vote

favorite












My uni tasked me with writing a program that reads the input and stores it into a dynamic 2D array, but we haven't covered that topic. I'm encountering a problem with my implementation, as it is skipping the first character in each line. I know the code is not top quality, but I just can't figure out why it skips the first char.



#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


#define MULT 3
#define DIV 2

char *read_line(int *col_size, int *max_c) {
char *line = NULL;
int size = *col_size;
int i, c;
line = malloc(size * sizeof *line);
for (i = 0; ((c = getchar()) != 'n') && (c != EOF); ++i) {
if (i == size) {
size = 1 + size * MULT / DIV;
line = realloc(line, size * sizeof *line);
assert(line != NULL);
}
line[i] = c;
}
if (i > *max_c)
*max_c = i;
if (size > *col_size)
*col_size = size;
return line;
}

char **read(int *row, int *col) {
char **input = NULL;
int row_size = 0;
int col_size = 0;
int i, c;
int max_c = 0;

for (i = 0; (c = getchar()) != EOF; ++i) {
if (i == row_size) {
row_size = 1 + row_size * MULT / DIV;
input = realloc(input, row_size * sizeof *input);
assert(input != NULL);
}
input[i] = read_line(&col_size, &max_c);
}
*row = i;
*col = max_c;
return input;
}


int main(void) {
int row_size, col_size, i, j;
char **board = read(&row_size, &col_size);
for (i = 0; i < row_size; ++i) {
for (j = 0; j < col_size; ++j)
putchar(board[i][j]);
putchar('n');
}
free(board);
return 0;
}









share|improve this question






















  • I've really only glanced at your code, but the one thing jumps out is you have ++i, not i++ in your for loops.
    – whoasked
    Nov 22 at 16:58






  • 4




    @whoasked It doesn't matter which one is used because that statement's value doesn't matter. It's not uncommon to use ++i because it may be slightly more efficient on some systems, depending on optimizations.
    – Thomas Jager
    Nov 22 at 17:08















up vote
0
down vote

favorite












My uni tasked me with writing a program that reads the input and stores it into a dynamic 2D array, but we haven't covered that topic. I'm encountering a problem with my implementation, as it is skipping the first character in each line. I know the code is not top quality, but I just can't figure out why it skips the first char.



#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


#define MULT 3
#define DIV 2

char *read_line(int *col_size, int *max_c) {
char *line = NULL;
int size = *col_size;
int i, c;
line = malloc(size * sizeof *line);
for (i = 0; ((c = getchar()) != 'n') && (c != EOF); ++i) {
if (i == size) {
size = 1 + size * MULT / DIV;
line = realloc(line, size * sizeof *line);
assert(line != NULL);
}
line[i] = c;
}
if (i > *max_c)
*max_c = i;
if (size > *col_size)
*col_size = size;
return line;
}

char **read(int *row, int *col) {
char **input = NULL;
int row_size = 0;
int col_size = 0;
int i, c;
int max_c = 0;

for (i = 0; (c = getchar()) != EOF; ++i) {
if (i == row_size) {
row_size = 1 + row_size * MULT / DIV;
input = realloc(input, row_size * sizeof *input);
assert(input != NULL);
}
input[i] = read_line(&col_size, &max_c);
}
*row = i;
*col = max_c;
return input;
}


int main(void) {
int row_size, col_size, i, j;
char **board = read(&row_size, &col_size);
for (i = 0; i < row_size; ++i) {
for (j = 0; j < col_size; ++j)
putchar(board[i][j]);
putchar('n');
}
free(board);
return 0;
}









share|improve this question






















  • I've really only glanced at your code, but the one thing jumps out is you have ++i, not i++ in your for loops.
    – whoasked
    Nov 22 at 16:58






  • 4




    @whoasked It doesn't matter which one is used because that statement's value doesn't matter. It's not uncommon to use ++i because it may be slightly more efficient on some systems, depending on optimizations.
    – Thomas Jager
    Nov 22 at 17:08













up vote
0
down vote

favorite









up vote
0
down vote

favorite











My uni tasked me with writing a program that reads the input and stores it into a dynamic 2D array, but we haven't covered that topic. I'm encountering a problem with my implementation, as it is skipping the first character in each line. I know the code is not top quality, but I just can't figure out why it skips the first char.



#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


#define MULT 3
#define DIV 2

char *read_line(int *col_size, int *max_c) {
char *line = NULL;
int size = *col_size;
int i, c;
line = malloc(size * sizeof *line);
for (i = 0; ((c = getchar()) != 'n') && (c != EOF); ++i) {
if (i == size) {
size = 1 + size * MULT / DIV;
line = realloc(line, size * sizeof *line);
assert(line != NULL);
}
line[i] = c;
}
if (i > *max_c)
*max_c = i;
if (size > *col_size)
*col_size = size;
return line;
}

char **read(int *row, int *col) {
char **input = NULL;
int row_size = 0;
int col_size = 0;
int i, c;
int max_c = 0;

for (i = 0; (c = getchar()) != EOF; ++i) {
if (i == row_size) {
row_size = 1 + row_size * MULT / DIV;
input = realloc(input, row_size * sizeof *input);
assert(input != NULL);
}
input[i] = read_line(&col_size, &max_c);
}
*row = i;
*col = max_c;
return input;
}


int main(void) {
int row_size, col_size, i, j;
char **board = read(&row_size, &col_size);
for (i = 0; i < row_size; ++i) {
for (j = 0; j < col_size; ++j)
putchar(board[i][j]);
putchar('n');
}
free(board);
return 0;
}









share|improve this question













My uni tasked me with writing a program that reads the input and stores it into a dynamic 2D array, but we haven't covered that topic. I'm encountering a problem with my implementation, as it is skipping the first character in each line. I know the code is not top quality, but I just can't figure out why it skips the first char.



#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


#define MULT 3
#define DIV 2

char *read_line(int *col_size, int *max_c) {
char *line = NULL;
int size = *col_size;
int i, c;
line = malloc(size * sizeof *line);
for (i = 0; ((c = getchar()) != 'n') && (c != EOF); ++i) {
if (i == size) {
size = 1 + size * MULT / DIV;
line = realloc(line, size * sizeof *line);
assert(line != NULL);
}
line[i] = c;
}
if (i > *max_c)
*max_c = i;
if (size > *col_size)
*col_size = size;
return line;
}

char **read(int *row, int *col) {
char **input = NULL;
int row_size = 0;
int col_size = 0;
int i, c;
int max_c = 0;

for (i = 0; (c = getchar()) != EOF; ++i) {
if (i == row_size) {
row_size = 1 + row_size * MULT / DIV;
input = realloc(input, row_size * sizeof *input);
assert(input != NULL);
}
input[i] = read_line(&col_size, &max_c);
}
*row = i;
*col = max_c;
return input;
}


int main(void) {
int row_size, col_size, i, j;
char **board = read(&row_size, &col_size);
for (i = 0; i < row_size; ++i) {
for (j = 0; j < col_size; ++j)
putchar(board[i][j]);
putchar('n');
}
free(board);
return 0;
}






c






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 22 at 16:54









guben

185




185












  • I've really only glanced at your code, but the one thing jumps out is you have ++i, not i++ in your for loops.
    – whoasked
    Nov 22 at 16:58






  • 4




    @whoasked It doesn't matter which one is used because that statement's value doesn't matter. It's not uncommon to use ++i because it may be slightly more efficient on some systems, depending on optimizations.
    – Thomas Jager
    Nov 22 at 17:08


















  • I've really only glanced at your code, but the one thing jumps out is you have ++i, not i++ in your for loops.
    – whoasked
    Nov 22 at 16:58






  • 4




    @whoasked It doesn't matter which one is used because that statement's value doesn't matter. It's not uncommon to use ++i because it may be slightly more efficient on some systems, depending on optimizations.
    – Thomas Jager
    Nov 22 at 17:08
















I've really only glanced at your code, but the one thing jumps out is you have ++i, not i++ in your for loops.
– whoasked
Nov 22 at 16:58




I've really only glanced at your code, but the one thing jumps out is you have ++i, not i++ in your for loops.
– whoasked
Nov 22 at 16:58




4




4




@whoasked It doesn't matter which one is used because that statement's value doesn't matter. It's not uncommon to use ++i because it may be slightly more efficient on some systems, depending on optimizations.
– Thomas Jager
Nov 22 at 17:08




@whoasked It doesn't matter which one is used because that statement's value doesn't matter. It's not uncommon to use ++i because it may be slightly more efficient on some systems, depending on optimizations.
– Thomas Jager
Nov 22 at 17:08












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted











for (i = 0; (c = getchar()) != EOF; ++i) {



in read() eats up the first character of a line before read_line() gets to see it. You'll have to find some other way to check for EOF. For example with



for (i = 0; !feof(stdin); ++i) {




Also, you don't zero-terminate your strings. Change your reading loop to



char *read_line(int *col_size, int *max_c) {
int size = *col_size ? *col_size : 1; // at least 1 for the terminating 0
char *line = malloc(size * sizeof *line);

if(!line)
return NULL;

int i, c;
for (i = 0; ((c = getchar()) != 'n') && (c != EOF); ++i) {
if(i == size) {
size = 2 + size * MULT / DIV; // note the 2
// ...
}
// ...
}
line[i] = '';


to do so.






for (i = 0; i < row_size; ++i) {
for (j = 0; j < col_size; ++j)
putchar(board[i][j]); // accesses memory that isn't yours
putchar('n'); // if not all rows are of the same length.
}



To avoid reading memory out-of-bounds, change that to



for (i = 0; i < row_size; ++i) {
for (j = 0; board[i][j] != ''; ++j)
putchar(board[i][j]);
putchar('n');
}


since you now have zero-terminated strings. Or why not just use puts()?



for (i = 0; i < row_size; ++i)
puts(board[i]);





free(board);



That won't deallocate the memory you allocated for the rows. You'd have to



for (i = 0; i < row_size; ++i)
free(bard[i]);
free(board);





share|improve this answer























  • Thank you so much! I see there's a lot I have to learn yet ;)))
    – guben
    Nov 22 at 20:04










  • Altough, it's possible that the program is going to try to place the '' at an index that isn't allocated, since it's outside the loop that checks wether i is small enough.
    – guben
    Nov 22 at 20:14










  • @guben You are right. size = 1 + size * MULT / DIV; should be size = 2 + size * MULT / DIV; Where does that idea of MULT / DIV come from?
    – Swordfish
    Nov 22 at 20:19












  • From the example code given by my uni professor, who said that usually, it's multiplied by 2, but here it's better to multiply by 3/2. He didn't tell us why though xD
    – guben
    Nov 22 at 20:37












  • Actually, Valgrind throws an invalid write error, when given an empty row :/
    – guben
    Nov 22 at 21:11











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53435425%2fdynamic-2d-array-in-c-not-reading-first-element%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted











for (i = 0; (c = getchar()) != EOF; ++i) {



in read() eats up the first character of a line before read_line() gets to see it. You'll have to find some other way to check for EOF. For example with



for (i = 0; !feof(stdin); ++i) {




Also, you don't zero-terminate your strings. Change your reading loop to



char *read_line(int *col_size, int *max_c) {
int size = *col_size ? *col_size : 1; // at least 1 for the terminating 0
char *line = malloc(size * sizeof *line);

if(!line)
return NULL;

int i, c;
for (i = 0; ((c = getchar()) != 'n') && (c != EOF); ++i) {
if(i == size) {
size = 2 + size * MULT / DIV; // note the 2
// ...
}
// ...
}
line[i] = '';


to do so.






for (i = 0; i < row_size; ++i) {
for (j = 0; j < col_size; ++j)
putchar(board[i][j]); // accesses memory that isn't yours
putchar('n'); // if not all rows are of the same length.
}



To avoid reading memory out-of-bounds, change that to



for (i = 0; i < row_size; ++i) {
for (j = 0; board[i][j] != ''; ++j)
putchar(board[i][j]);
putchar('n');
}


since you now have zero-terminated strings. Or why not just use puts()?



for (i = 0; i < row_size; ++i)
puts(board[i]);





free(board);



That won't deallocate the memory you allocated for the rows. You'd have to



for (i = 0; i < row_size; ++i)
free(bard[i]);
free(board);





share|improve this answer























  • Thank you so much! I see there's a lot I have to learn yet ;)))
    – guben
    Nov 22 at 20:04










  • Altough, it's possible that the program is going to try to place the '' at an index that isn't allocated, since it's outside the loop that checks wether i is small enough.
    – guben
    Nov 22 at 20:14










  • @guben You are right. size = 1 + size * MULT / DIV; should be size = 2 + size * MULT / DIV; Where does that idea of MULT / DIV come from?
    – Swordfish
    Nov 22 at 20:19












  • From the example code given by my uni professor, who said that usually, it's multiplied by 2, but here it's better to multiply by 3/2. He didn't tell us why though xD
    – guben
    Nov 22 at 20:37












  • Actually, Valgrind throws an invalid write error, when given an empty row :/
    – guben
    Nov 22 at 21:11















up vote
1
down vote



accepted











for (i = 0; (c = getchar()) != EOF; ++i) {



in read() eats up the first character of a line before read_line() gets to see it. You'll have to find some other way to check for EOF. For example with



for (i = 0; !feof(stdin); ++i) {




Also, you don't zero-terminate your strings. Change your reading loop to



char *read_line(int *col_size, int *max_c) {
int size = *col_size ? *col_size : 1; // at least 1 for the terminating 0
char *line = malloc(size * sizeof *line);

if(!line)
return NULL;

int i, c;
for (i = 0; ((c = getchar()) != 'n') && (c != EOF); ++i) {
if(i == size) {
size = 2 + size * MULT / DIV; // note the 2
// ...
}
// ...
}
line[i] = '';


to do so.






for (i = 0; i < row_size; ++i) {
for (j = 0; j < col_size; ++j)
putchar(board[i][j]); // accesses memory that isn't yours
putchar('n'); // if not all rows are of the same length.
}



To avoid reading memory out-of-bounds, change that to



for (i = 0; i < row_size; ++i) {
for (j = 0; board[i][j] != ''; ++j)
putchar(board[i][j]);
putchar('n');
}


since you now have zero-terminated strings. Or why not just use puts()?



for (i = 0; i < row_size; ++i)
puts(board[i]);





free(board);



That won't deallocate the memory you allocated for the rows. You'd have to



for (i = 0; i < row_size; ++i)
free(bard[i]);
free(board);





share|improve this answer























  • Thank you so much! I see there's a lot I have to learn yet ;)))
    – guben
    Nov 22 at 20:04










  • Altough, it's possible that the program is going to try to place the '' at an index that isn't allocated, since it's outside the loop that checks wether i is small enough.
    – guben
    Nov 22 at 20:14










  • @guben You are right. size = 1 + size * MULT / DIV; should be size = 2 + size * MULT / DIV; Where does that idea of MULT / DIV come from?
    – Swordfish
    Nov 22 at 20:19












  • From the example code given by my uni professor, who said that usually, it's multiplied by 2, but here it's better to multiply by 3/2. He didn't tell us why though xD
    – guben
    Nov 22 at 20:37












  • Actually, Valgrind throws an invalid write error, when given an empty row :/
    – guben
    Nov 22 at 21:11













up vote
1
down vote



accepted







up vote
1
down vote



accepted







for (i = 0; (c = getchar()) != EOF; ++i) {



in read() eats up the first character of a line before read_line() gets to see it. You'll have to find some other way to check for EOF. For example with



for (i = 0; !feof(stdin); ++i) {




Also, you don't zero-terminate your strings. Change your reading loop to



char *read_line(int *col_size, int *max_c) {
int size = *col_size ? *col_size : 1; // at least 1 for the terminating 0
char *line = malloc(size * sizeof *line);

if(!line)
return NULL;

int i, c;
for (i = 0; ((c = getchar()) != 'n') && (c != EOF); ++i) {
if(i == size) {
size = 2 + size * MULT / DIV; // note the 2
// ...
}
// ...
}
line[i] = '';


to do so.






for (i = 0; i < row_size; ++i) {
for (j = 0; j < col_size; ++j)
putchar(board[i][j]); // accesses memory that isn't yours
putchar('n'); // if not all rows are of the same length.
}



To avoid reading memory out-of-bounds, change that to



for (i = 0; i < row_size; ++i) {
for (j = 0; board[i][j] != ''; ++j)
putchar(board[i][j]);
putchar('n');
}


since you now have zero-terminated strings. Or why not just use puts()?



for (i = 0; i < row_size; ++i)
puts(board[i]);





free(board);



That won't deallocate the memory you allocated for the rows. You'd have to



for (i = 0; i < row_size; ++i)
free(bard[i]);
free(board);





share|improve this answer















for (i = 0; (c = getchar()) != EOF; ++i) {



in read() eats up the first character of a line before read_line() gets to see it. You'll have to find some other way to check for EOF. For example with



for (i = 0; !feof(stdin); ++i) {




Also, you don't zero-terminate your strings. Change your reading loop to



char *read_line(int *col_size, int *max_c) {
int size = *col_size ? *col_size : 1; // at least 1 for the terminating 0
char *line = malloc(size * sizeof *line);

if(!line)
return NULL;

int i, c;
for (i = 0; ((c = getchar()) != 'n') && (c != EOF); ++i) {
if(i == size) {
size = 2 + size * MULT / DIV; // note the 2
// ...
}
// ...
}
line[i] = '';


to do so.






for (i = 0; i < row_size; ++i) {
for (j = 0; j < col_size; ++j)
putchar(board[i][j]); // accesses memory that isn't yours
putchar('n'); // if not all rows are of the same length.
}



To avoid reading memory out-of-bounds, change that to



for (i = 0; i < row_size; ++i) {
for (j = 0; board[i][j] != ''; ++j)
putchar(board[i][j]);
putchar('n');
}


since you now have zero-terminated strings. Or why not just use puts()?



for (i = 0; i < row_size; ++i)
puts(board[i]);





free(board);



That won't deallocate the memory you allocated for the rows. You'd have to



for (i = 0; i < row_size; ++i)
free(bard[i]);
free(board);






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 22 at 20:24

























answered Nov 22 at 17:18









Swordfish

1




1












  • Thank you so much! I see there's a lot I have to learn yet ;)))
    – guben
    Nov 22 at 20:04










  • Altough, it's possible that the program is going to try to place the '' at an index that isn't allocated, since it's outside the loop that checks wether i is small enough.
    – guben
    Nov 22 at 20:14










  • @guben You are right. size = 1 + size * MULT / DIV; should be size = 2 + size * MULT / DIV; Where does that idea of MULT / DIV come from?
    – Swordfish
    Nov 22 at 20:19












  • From the example code given by my uni professor, who said that usually, it's multiplied by 2, but here it's better to multiply by 3/2. He didn't tell us why though xD
    – guben
    Nov 22 at 20:37












  • Actually, Valgrind throws an invalid write error, when given an empty row :/
    – guben
    Nov 22 at 21:11


















  • Thank you so much! I see there's a lot I have to learn yet ;)))
    – guben
    Nov 22 at 20:04










  • Altough, it's possible that the program is going to try to place the '' at an index that isn't allocated, since it's outside the loop that checks wether i is small enough.
    – guben
    Nov 22 at 20:14










  • @guben You are right. size = 1 + size * MULT / DIV; should be size = 2 + size * MULT / DIV; Where does that idea of MULT / DIV come from?
    – Swordfish
    Nov 22 at 20:19












  • From the example code given by my uni professor, who said that usually, it's multiplied by 2, but here it's better to multiply by 3/2. He didn't tell us why though xD
    – guben
    Nov 22 at 20:37












  • Actually, Valgrind throws an invalid write error, when given an empty row :/
    – guben
    Nov 22 at 21:11
















Thank you so much! I see there's a lot I have to learn yet ;)))
– guben
Nov 22 at 20:04




Thank you so much! I see there's a lot I have to learn yet ;)))
– guben
Nov 22 at 20:04












Altough, it's possible that the program is going to try to place the '' at an index that isn't allocated, since it's outside the loop that checks wether i is small enough.
– guben
Nov 22 at 20:14




Altough, it's possible that the program is going to try to place the '' at an index that isn't allocated, since it's outside the loop that checks wether i is small enough.
– guben
Nov 22 at 20:14












@guben You are right. size = 1 + size * MULT / DIV; should be size = 2 + size * MULT / DIV; Where does that idea of MULT / DIV come from?
– Swordfish
Nov 22 at 20:19






@guben You are right. size = 1 + size * MULT / DIV; should be size = 2 + size * MULT / DIV; Where does that idea of MULT / DIV come from?
– Swordfish
Nov 22 at 20:19














From the example code given by my uni professor, who said that usually, it's multiplied by 2, but here it's better to multiply by 3/2. He didn't tell us why though xD
– guben
Nov 22 at 20:37






From the example code given by my uni professor, who said that usually, it's multiplied by 2, but here it's better to multiply by 3/2. He didn't tell us why though xD
– guben
Nov 22 at 20:37














Actually, Valgrind throws an invalid write error, when given an empty row :/
– guben
Nov 22 at 21:11




Actually, Valgrind throws an invalid write error, when given an empty row :/
– guben
Nov 22 at 21:11


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53435425%2fdynamic-2d-array-in-c-not-reading-first-element%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

What visual should I use to simply compare current year value vs last year in Power BI desktop

Alexandru Averescu

Trompette piccolo