The program creates a 2D array with malloc and func fills it. fprintf writes in a file. That's all folks.
But I am getting unexpected program exit form the program if I use big integers for height and width.
(30,60): OK
(60,80): not OK
(60,65): OK
(17,41): OK
(200,200): not OK
Does anybody have a clue?
int main() {
unsigned char **buf = (unsigned char **)malloc(height * sizeof(unsigned char*));
for (int i = 0; i < height; ++i)
buf[i] = (unsigned char *)malloc(width * sizeof(unsigned char));
func(buf);
FILE * f = fopen("foo.txt", "w+");
for(int i= 0;i<height;++i)
fprintf(f, "%s%c", buf[i], '\n');
fclose(f);
for (int i = 0; i < height; ++i)
free(buf[i]);
free(buf);
}
void func(unsigned char** buf) {
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j)
buf[i][j] = 48 + (i/10)%10;
buf[i][width] = '\0';
}
}
You need to allocate space for '\0'
buf[i] = (unsigned char *)malloc(image_width * sizeof(unsigned char));
buf[i][width] = '\0';
buf[i][width] does not exist
Try
buf[i] = malloc(image_width + 1);
This line writes outside the array.
buf[i][width] = '\0';
You need to allocate one more character.
buf[i] = (unsigned char *)malloc((width + 1) * sizeof(unsigned char));
And make sure to use height and width everywhere.
Related
I want to repeat a string - for example hello - for a specific number of imes - for example 3 times -, but it doesnt work :) The example should look like this: hellohellohello, but I get no output or i get HHHHHHHHHHH...
here is my code:
char *repeat_str(size_t count, char *src) {
int length = strlen(src);
int z = length;
char *ausgabe = calloc((length*(count+1)), sizeof(char));
for(int i = 0; i<=((int) count);i++){
for(int j =0; j< length; j++){
ausgabe[i+j+z] = src[j];
}
z=z*2;
}
//printf("%s\n", ausgabe);
return(ausgabe);
}
If i remove the 'z' in the brackets of 'ausgabe', i get the output HHHHHHHH%, with the z I just get no output. Could bdy pls help me change this behavoiur - and more important, understant why it does that?
As you are always referring *src, which is fixed to the first letter of src,
the result looks like repeating it. Would you please try instead:
char *repeat_str(size_t count, char *src) {
int length = strlen(src);
char *ausgabe = calloc(length * count + 1, sizeof(char));
for (int i = 0; i < count; i++) {
for (int j = 0; j < length; j++) {
ausgabe[i * length + j] = src[j];
}
}
//printf("%s\n", ausgabe);
return ausgabe;
}
The strcat function is your friend. We can calloc a buffer long enough for n source strings, plus one for the null terminator, and then just concatenate the source string onto that buffer n times.
char *repeat_string(int n, const char *s) {
int len = strlen(s) * n + 1;
char *result = calloc(len, 1);
if (!result) return NULL;
for (int i = 0; i < n; i++) {
strcat(result, s);
}
return result;
}
I've been given a task that requires a dynamic 2D array in C, but we haven't even covered pointers yet, so I'm kind of at a loss here. I have to read some text input and store it in a 2D array, without limiting its size.
Unfortunately, Valgrind keeps throwing me an error saying that there's an uninitialised value, when the puts() function executes and sometimes it prints out some random signs. I understand that I must have omitted some indexes, but I just can't find where the issue stems from. Additionally, all advices regarding the quality of my code are very much appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#define MULT 3
#define DIV 2
char **read(int *row, int *col) {
char **input = NULL;
int row_size = 0;
int col_size = 0;
int i = 0;
int c;
while ((c = getchar()) != EOF) {
if (c != '\n') { // skip empty lines
assert(i < INT_MAX);
if (i == row_size) { // if not enough row memory, allocate more
row_size = 1 + row_size * MULT / DIV;
input = realloc(input, row_size * sizeof *input);
assert(input != NULL);
}
char *line = NULL;
int j = 0;
// I need all the rows to be of the same size (see last loop)
line = malloc(col_size * sizeof *line);
// do while, so as to not skip the first character
do {
assert(j < INT_MAX-1);
if (j == col_size) {
col_size = 1 + col_size * MULT / DIV;
line = realloc(line, col_size * sizeof *line);
assert(line != NULL);
}
line[j++] = c;
} while(((c = getchar()) != '\n') && (c != EOF));
// zero-terminate the string
if (j == col_size) {
++col_size;
line = realloc(line, col_size * sizeof *line);
line[j] = '\0';
}
input[i++] = line;
}
}
// Here I give all the lines the same length
for (int j = 0; j < i; ++j)
input[j] = realloc(input[j], col_size * sizeof *(input+j));
*row = i;
*col = col_size;
return input;
}
int main(void) {
int row_size, col_size, i, j;
char **board = read(&row_size, &col_size);
// Initialize the remaining elements of each array
for (i = 0; i < row_size; ++i) {
j = 0;
while (board[i][j] != '\0')
++j;
while (j < col_size-1)
board[i][++j] = ' ';
}
for (i = 0; i < row_size; ++i) {
puts(board[i]);
}
for (i = 0; i < row_size; ++i)
free(board[i]);
free(board);
return 0;
}
I don't know why but my code prints a list of (null)(null)(null)....
I have to print the list of words from a file 'words.txt'.
Another question is: fscanf ignore white spaces?
#define WORD_LENGTH 1024
#define SIZE_QUOTE 100
int main(){
char **quote = malloc(sizeof(char*) * (size_t)SIZE_QUOTE);
long i;
for(i = 0; i < SIZE_QUOTE; i++){
if(!(malloc(sizeof(char) * (size_t)WORD_LENGTH)))
exit(1);
}
i = 0;
FILE *pf = fopen("words.txt", "r");
while(!feof(pf) && i < SIZE_QUOTE){
fscanf(pf, "%s", quote[i]);
printf("%s", quote[i]);
i++;
}
fclose(pf);
free(quote);
}
You're never assigning the return value of malloc() to quote[i] so they end up staying NULL (if you're lucky):
char **quote = malloc(sizeof(char*) * (size_t)SIZE_QUOTE);
long i;
for(i = 0; i < SIZE_QUOTE; i++){
if(!(malloc(sizeof(char) * WORD_LENGTH)))
It should be something like this instead:
char **quote = malloc(sizeof(char*) * (size_t)SIZE_QUOTE);
for(int i = 0; i < SIZE_QUOTE; i++){
quote[i] = malloc(sizeof(char) * WORD_LENGTH);
if(!quote[i])
Also you could avoid malloc() entirely and statically initialize that array if all the sizes are known:
char quote[SIZE_QUOTE][WORD_LENGTH] = {{'\0'}};
Also, you should be free()-ing the individual quote[i] at the end too:
for(int i = 0; i < SIZE_QUOTE; ++i) free(quote[i]);
free(quote);
There's other mistakes that have been pointed out through the comments already, so I won't elaborate further.
In Python, one can print XXXX using print "X"*4; Is there any easy equivalent in C?
C doesn't have much in the way of builtin/standard library, so you'd have to go through the process of allocating a new buffer and concatenating four strings to it, then freeing the buffer, it's simpler just to print "X" four times.
int i;
for (i=0; i<4; ++i) {
printf("X");
}
printf("\n");
You could write your own, though.
char* x(const char* s, unsigned int reps) {
size_t len = strlen(s);
char* buf = (char*)malloc(len*reps + 1);
while (reps--) {
memcpy(buf, s, len);
buf += len;
}
*buf = '\0';
return buf;
}
char* repeated = x("X", 4);
printf("%s\n", repeated);
free(repeated);
But as you can see, the result is almost as long.
Yes. Welcome to C:
int i;
for (i=0; i<4; i++)
printf("X");
Not really. In C you would need to use a loop.
No there is no standard library in C that can do that, but you can always implement easily with yourself. A simple implementation in C:
char * strmul(const char * src, size_t times) {
size_t s_len = strlen(src);
char * res = (char*)malloc(s_len * times + 1);
int i;
for(i = 0; i < times; i++) {
strcpy(res + s_len * i, src);
}
return res;
}
Improved version as suggested by #ikegami
char * strmul(const char * src, size_t times) {
size_t s_len = strlen(src);
char * res = (char*)malloc(s_len * times + 1);
int i;
for(i = 0; i < times; i++) {
memcpy(res + s_len * i, src);
}
res[s_len * times + 1] = '\0';
return res;
}
Program for work with arrays in dynamic memory.
Need equivalent for C. Can anybody help?
const int n = 6;
char **words = (char**) malloc(n *sizeof(char*));
for(int i = 0 ; i < n; i++)
words[i] = (char*)malloc( 50 * sizeof(int));
for(int i = 0; i < n; i++)
{
cin>>words[i];
}
cout<<endl;
for(int i = 0; i < n; i++)
{
if(words[i][0] == 'q')
cout<<words[i]<<endl;
}
The only C++ parts there are cin and cout; you can change them easily:
cin>>words[i];
becomes
scanf("%s", words[i]);
or
gets(words[i]);
while
cout<<words[i]<<endl;
becomes
puts(words[i]);
By the way, in the cin/scanf/gets you have a potential buffer overflow, since you are allocating space for 6 characters but you are accepting input of any length. You should do instead:
scanf("%6s", words[i]);
or (more maintainable, since it uses n directly)
fgets(words[i], n, stdin);
(although this will include the trailing \n in the string)
The only C++ features you are using are cin and cout. replace cin>>words[i] with gets(words[i]) and cout<<words[i]<<endl with puts(words[i]).
Use scanf("%s", &words[i]) to input data from stdin and printf("%s\n", words[i]) to output to stdout.
As you wish:
const int n = 6;
char **words = (char**) malloc(n *sizeof(char*));
int i = 0;
for( i= 0 ; i < n; i++)
{
words[i] = (char*)malloc( 50 * sizeof(char));
}
for(i = 0; i < n; i++)
{
scanf("%s", words[i]);
}
printf("\n");
for(i = 0; i < n; i++)
{
if(words[i][0] == 'q')
printf("%s\n", words[i]);
}