Dynamically allocate an array of strings - arrays

How can I fix this code in a way that it prints the words in the array? Moreover this is the right way to dynamically allocate memory for n words of max size 40?
int main() {
int n;
char *arr;
int i;
printf("Give me a number:");
scanf("%d", &n);
arr = malloc(n * 40);
for (i = 0; i < n; i++)
{
printf("Give me a word: ");
scanf("%s", &arr[i]);
}
for (i = 0; i < n; i++)
{
printf("%s", arr[i]); //< --problem here
}
return 0;
}

Your allocation is not the best, and printf argument arr[i] expects a char* but you pass it an int (a char if you'd like).
Here is how you should do it, with comments:
Live demo
#include <stdio.h>
#include <stdlib.h> //for malloc
int main(){
int n;
int i;
printf("Give me a number:");
scanf("%d", &n);
//declare a variable of pointer to pointer to char
//allocate memory for the array of pointers to char,
//each one capable of pointing to a char array
char **arr = malloc(n * sizeof *arr);
if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}
//allocate memory for each individual char array
for(i = 0; i < n; i++){
arr[i] = malloc(40); //char size is always 1 byte
if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}
}
for (i = 0; i < n; i++){
printf("Give me a word: ");
//limit the size of read input to 39 charaters to avoid overflow,
//a nul character will be added by scanf
scanf("%39s", arr[i]);
}
for (i = 0; i < n; i++){
printf("%s\n", arr[i]);
}
for(int i = 0; i < n; i++){ //free the memory for each char array
free(arr[i]);
}
free(arr); //free array of pointers
return 0;
}
You can also do this with less code using a pointer to array of 40 chars, this will simplify the memory allocation and deallocation:
Sample with comments:
Live demo
#include <stdio.h>
#include <stdlib.h> //for malloc
int main(){
int n;
int i;
printf("Give me a number:");
scanf("%d", &n);
//declare a pointer to array of chars and
//allocate memory for all the char arrays
char (*arr)[40] = malloc(n * sizeof *arr);
if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}
for (i = 0; i < n; i++){
printf("Give me a word: ");
scanf("%39s", arr[i]);
}
for (i = 0; i < n; i++){
printf("%s\n", arr[i]);
}
free(arr); //free allocated memory
return 0;
}

This:
for(i=0;i<n;i++){
printf("Give me a word: ");
scanf("%s",&arr[i]);
}
is probably not what you want.
You probably want this instead:
for(i=0; i<n; i++){
printf("Give me a word: ");
scanf("%s", arr + i*40);
}
then later:
for(i=0; i<n; i++){
printf("%s", arr + i*40);
}
Remember that a string in C is just an array of characters.
Thus when defining char *arr, you are creating a single string. Had you done char **arr it would have been an array of strings, which is what you want.
However, I find that allocating/freeing arrays of arrays on the heap to be rather inconvenient, and prefer 'flattening' them into a single array.
This is exactly what you were doing with arr = malloc(n*40), but then later you treated this array of characters as an array of strings when you did this:
for(i=0; i<n; i++){
printf("Give me a word: ");
scanf("%s", &arr[i]);
}
Note that this is actually perfectly legal (scanf wanted a char* and you gave it one), but it's a logical error since you are giving it the n-th character when you wanted to give it the n-th array.
And oh yes, don't forget to free(arr) later.

Related

Print the string using dynamically memory allocated

Hello, my question is: How to print out string 1 and string 2, not only string 2. I am new to dynamically memory allocated. My sample code is below, thanks for your help.
Result expected:
Hello
My name is Ken
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
int n, i;
char *ptr;
printf("How many strings you want to display?: ");
scanf("%d", &n);
ptr = (char*)malloc(n * sizeof(n));
if(ptr == NULL){
printf("Failed to allocate the memory to string!\n");
exit(0);
}
for(i = 0; i < n; i++){
printf("String %d: ", i + 1);
fflush(stdin);
scanf("%[^\n]", ptr);
}
printf("\n");
printf("Strings you entered:\n");
for(i = 0; i < n; i++){
printf("%s\n", ptr);
}
}
Please check the below code. I have marked modified lines with a comment starting with // CHANGE.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// CHANGE - free memory when not needed
void free_memory(char** ptr, int n)
{
if (ptr)
{
int i;
for (i = 0; i < n; i++)
{
if (ptr[i])
{
free(ptr[i]);
}
}
free(ptr);
}
}
int main(){
int n, i;
char **ptr; // CHANGE - make a double pointer - array of strings (imagine rows and columns)
printf("How many strings you want to display?: ");
scanf("%d", &n);
ptr = (char**) malloc(n * sizeof(char*)); // CHANGE - allocate memory based on no. of rows (columns are string characters)
if (ptr == NULL) {
printf("Failed to allocate the memory to string!\n");
exit(1);
}
getchar(); // CHANGE - read the newline character else fgets doesn't work
for (i = 0; i < n; i++) {
ptr[i] = (char*) malloc(256 * sizeof(char)); // CHANGE - allocate memory for each row
printf("String %d: ", i + 1);
if ( fgets(ptr[i], 256 * sizeof(char), stdin) == NULL ) {
printf("Failed to get line input\n");
free_memory(ptr, n);
exit(1);
}
ptr[i][strlen(ptr[i]) - 1] = '\0'; // CHANGE - remove extra newline character at the end
}
printf("\n");
printf("Strings you entered:\n");
for (i = 0; i < n; i++) {
printf("%s\n", ptr[i]); // CHANGE - print each row
}
free_memory(ptr, n);
return 0;
}
First, there are two numbers that should be decided:
the number of strings the user wants to input and
the length of the strings (or the lengths of each string).
Each string will be stored in a char*. And all strings together will be stored in a char**. The length of char** will be your n in this case.
And length of each char* can be decided however you want.
I prefer to use a directive #define to define a constant like 100.
You can also do a global or local variable or just a digit.
Also don't forget to free anything you allocate. Check below for details.
And happy coding!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_STRING_SIZE 100
int main(){
int n, i;
// stores all the strings
char **ptr;
printf("How many strings you want to display?: ");
scanf("%d", &n);
// allocate memory of size (n * size of char*)
ptr = (char**)malloc(n * sizeof(char*));
if(ptr == NULL){
printf("Failed to allocate the memory to string!\n");
// for portability to use EXIT_FAILURE,
// which is defined in the standard library
exit(EXIT_FAILURE);
}
// for each pointer, allocate memory of size (MAX_STRING_SIZE * size of char)
for(i = 0; i < n; i++)
// I should put a validity check here but I'm too lazy...
ptr[i] = (char*)malloc(MAX_STRING_SIZE * sizeof(char));
for(i = 0; i < n; i++){
printf("String %d: ", i + 1);
fflush(stdin);
scanf("%[^\n]", ptr[i]); // use ptr[i]
}
printf("\n");
printf("Strings you entered:\n");
for(i = 0; i < n; i++){
printf("%s\n", ptr[i]); // use ptr[i]
}
// free all of them
for(i = 0; i < n; i++)
free(ptr[i]);
free(ptr);
return 0;
}

I want to print all the input of this string in for loop but it only prints the last input

Help me correcting this code.... I don't know what extra details should I give so it lets me post.
#include<stdio.h>
int main(){
char s[34];
int a = 4;
for (int i = 0; i < a; i++)
{
printf("Student %d enter your name: ", i+1);
scanf("%s", s);
}
for (int i = 0; i < a; i++)
{
printf("Student %d name is %s\n", i+1, s);
}
return 0;
}
You are overwriting the same block of memory: scanf("%s", s);.
You should have s as an array of pointers to char i.e. char *s[4] in which case you should allocate space for each name using malloc and then use free to give back all allocated memory to the OS.
Or, you could declare s to be char s[4][34] and use s[i] in your scanf and printf statements.

rearranging a char array with strncpy in C

I am trying to change the sorting of a the arr list which could consist of zero, one, two as the inputted and stored values for arr. The stringreplace function is meant to shift every single element by one so the new sorting would be one, two, zero. I am trying to replace the elements with one another by using the strncpy function but I think it is a bit faulty, how could i fix this?
strncpy function
char stringreplace( char a[], int b){
for(int j = 0; j > b -1; j++){
strncpy(a[j], a[j+1], sizeof(a));}
for(int j = 0; j > b; j++){
printf("%s",a[j]);}
}
main function
int main()
{
char input[100];
char arr[100]= {0};
int number;
printf("Input the number of strings: ");
scanf("%d", &number);
for(int i= 0; i < number; i++){
printf("Input the number of strings: ");
scanf("%s", input);
arr[i] = input;
}
stringreplace(arr, number);
return 0;
}
You may consider allocating strings dynamically, assigning a pointer for each string into an array words, and then rotating each pointer in the array to the left.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void lrot_words(char *words[], int n);
int main(void)
{
char *p, word[100], *words[100];
int i, num_words;
printf("Enter the number of words: ");
scanf("%d", &num_words);
for(i = 0; i < num_words; i++){
printf("Enter a word: ");
scanf("%s", word);
if ((p = malloc(strlen(word) + 1)) == NULL) {
fprintf(stderr, "Error: malloc failed\n");
exit(EXIT_FAILURE);
}
words[i] = strcpy(p, word);
}
lrot_words(words, num_words);
for (i = 0; i < num_words; i++) {
printf("%s\n", words[i]);
}
return 0;
}
void lrot_words(char *words[], int n)
{
char *temp = words[0];
int i;
for (i = 0; i < n - 1; i++) {
words[i] = words[i+1];
}
words[i] = temp;
}

Compare arrays of words in C

How I can compare 2d arrays of char in C?
I tried this
Char **arr_1;
Char **arr_2;
...// malloc. Its OK.
for (I=0; I<n; I++)
{
If (strcmp (arr_1[I],arr_2[I])==0)
// do smth
}
But it doesn't work . I'm not good in pointers.
Arrays have some array of words.
Ubuntu gcc
Without strcmp, the program works.
Thanks
You can do it.
char arr_1[10][10];
char arr_2[10][10];
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf(" %[^\n]",arr_1[i]);
scanf(" %[^\n]",arr_2[i]);
}
for(int I=0; I<n; I++)
{
if(strcmp (arr_1[I],arr_2[I])==0)
{
// do smth
}
}
you must be allocating 2D dynamic array wrong.
consider this code:
int SIZE=5;
char **arr_1;
arr_1 = malloc(SIZE* sizeof(char *)); //initialising an array of pointers
char **arr_2;
arr_2 = malloc(SIZE* sizeof(char *)); //initialising an array of pointers
for(i=0;i<SIZE;i++)
{
printf(" Enter a name\n");
arr_1[i]=malloc(100*sizeof(char)); //for each pointer in this array allocate an array of characters
scanf("%99s",arr_1[i]);
}
for(i=0;i<SIZE;i++)
{
printf(" Enter a name\n");
arr_2[i]=malloc(100*sizeof(char)); //for each pointer in this array allocate an array of characters
scanf("%99s",arr_2[i]);
}
for(i=0;i<SIZE;i++)
{
if(strcmp(arr_1[i],arr_2[i])==0)
//do smthing
}

C : Array of strings - Can input only n-1 strings for an input size of n

I have to sort strings in a lexicographical order using the Bubble Sort technique without using any library functions. I have written the following code which is working fine in sorting the strings.
But the problem is that if I give n as the input (say n = 4), I can enter only n-1 strings (only 3 strings).
The problem can be solved by running the for loops from 0 to n, but that isn't a logical solution.
What am I doing wrong here?
#include <stdio.h>
#include <string.h>
#include <malloc.h>
void swap(int indx[], int j)
{
int temp;
temp = indx[j];
indx[j] = indx[j+1];
indx[j+1] = temp;
}
void sort(char **str, int indx[], int n)
{
int i, j, k;
for(i=0; i<n; i++)
{
for(j=0; j<n-i-1; j++)
{
k = 0;
while(str[j][k] != '\0')
{
if((str[indx[j]][k]) > (str[indx[j+1]][k]))
{
swap(indx, j);
break;
}
else if((str[indx[j]][k]) < (str[indx[j+1]][k]))
break;
else
k++;
}
}
}
}
void display(char **str, int indx[], int n)
{
int i;
printf("Sorted strings : ");
for(i=0; i<n; i++)
printf("%s\n", str[indx[i]]);
}
int main(void)
{
char **str;
int n, i, j, *indx;
printf("Enter no. of strings : ");
scanf("%d", &n);
str = (char **) malloc (n * (sizeof(char *)));
indx = (int *) malloc (n * sizeof(int));
for(i=0; i<n; i++)
str[i] = (char *)malloc(10 * sizeof(char));
printf("Enter the strings : ");
for(i=0; i<n; i++)
{
gets(str[i]);
indx[i] = i;
}
sort(str, indx, n);
display(str, indx, n);
}
The problem is your use of scanf(). When you do scanf("%d", &n), the scanf() function reads input until it finds an integer, and puts the value into n. However, when you entered that integer, you didn't just type '4', you typed '4' and pressed Enter. And the newline is still in the input buffer. The gets() function, on the other hand, reads input up to and including the first newline, and the newline character is discarded. So when you're reading the input strings, the gets call to gets() reads the newline, and returns immediately. And then, the first string that you enter is read by the second call to gets()...
Incidentally, The gets() function should never, ever, under any circumstances, ever be used for real programs, because it doesn't allow you to limit input. Better would be to use fgets(). fgets(str[i], BUFFERSIZE-1, stdin).
int main(void)
{
char **str;
int n=4, i, j, *indx;
printf("Enter no. of strings : ");
//scanf("%d", &n);
str = (char **) malloc (n * (sizeof(char *)));
indx = (int *) malloc (n * sizeof(int));
for(i=0; i<n; i++)
str[i] = (char *)malloc(10 * sizeof(char));
printf("Enter the strings : ");
for(i=0; i<n; i++)
{
gets(str[i]);
indx[i] = i;
}
sort(str, indx, n);
display(str, indx, n);
}
//if i comment out scanf and give int the value it works fine //
so the problem is use of fgets just after scanf as scanf leave a newline character in the buffer// so consume it before using fgets
Try this at the line where you have to input the string. Instead of:
gets(str[i]);
type:
scanf("%s",str[i]);

Resources