Element in First Index Doesn't Behave as the Rest - c

so I'm trying to do a very simple task. I need to write a function that gets an empty array of strings and its size and initialize it (for example "names={"dani", "gabi", "bobi"}, names is array of size 3 and each one hold a string that the user inputs). So first the user needs to put the size then I allocate the array and then I trying to get strings for the array each one for different address.
Now for some reason it works great for the rest of the array except for the one in the first index (arr[0]). I understand that because the "ENTER" is a char it gets it for the first string (when the user inputs the size)
But I don't want it to be like this and I'm trying to fix it for hours and I'm hopeless
#define _CRT_SECURE_NO_WARNINGS#define SIZE 21
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { FAIL = 0, SUCCESS = 1 };
int init_arr(char ***arr, int *size);
int main()
{
int i, sizes = 0;
char **course = NULL;
init_arr(&course, &sizes);
for (i = 0; i< sizes; i++)
puts(course[i]);
free(course);
return 0;
}
int init_arr(char ***arr, int *size)
{
int i;
char* c;
printf("Enter the Number of--->:");
scanf("%d", size);
*arr = (char**)malloc((*size) * sizeof(char*));
if ((*arr) == NULL)
{
printf("Error");
return FAIL;
}
for (i = 0; i < (*size); i++)
{
c = (char*)calloc(SIZE, sizeof(char));
if (c == NULL)
{
printf("Error");
return FAIL;
}
printf("Enter Name %d-->:", i);
fgets(c, SIZE, stdin);
(*arr)[i] = c;
}
return SUCCESS;
}

getchar(); will do the work:
printf("Enter the Number of--->:");
scanf("%d", size);
getchar(); // to read newline character

Related

How to dynamically allocate 2d array when you dont know how many words will user input?

I want to make a program that stores inputed words into a 2D array (it can be as many as you want) and once you input word 'end', program should get out of the while loop. If I for example input these:
word1
word2
longer-word
end
Then the output should be:
List of words are:
word1
word2
longer-word
But here's the problem, I obviously dont know how many words will user input ( I dynamically allocated 2d array 5*20, so max 5 words), so what's the "correct" way of dynamically allocating 2D array, do I have to somehow reallocate every time user input new word or what? I really have no idea how to do it.
Here's a code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** allocate(int n, int m) {
char** arr = (char**)malloc(sizeof(char*) * n);
for (int i = 0; i < n; i++)
arr[i] = (char*)malloc(sizeof(char) * m);
return arr;
}
void print(char** words, int n, int m) {
printf("List of words: \n");
for (int i = 0; i < n; i++) {
printf("%s\n", words[i]);
}
}
int main() {
char** words = allocate(5,20);
char input[20];
int index = 0;
while ( strcmp("end", input) ) {
scanf(" %s", input);
if (strcmp("end", input) != 0) {
strcpy(words[index], input);
index++;
}
}
print(words, 5, 20);
return 0;
}
And also I noticed that when you input two words( with space ) it outputs those 2 words separately, so how can i prevent this?
What you need to is guess a reasonable size and allocate that. As you allocate your words you need to check that your limit is not hit. If it will be hit, then you need to realloc your array with a bigger size. A common strategy is to double the size each time.
the array in c/c++ cannot be have a variable so this problem cannot be solved like this, also you can think of this 2d array as 1d array of strings.
this is the solution that i came up with:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORD_SIZE 20
char **allocate(int n, int m) {
char **arr = (char **) malloc(sizeof(char *) * n);
for (int i = 0; i < n; i++)
arr[i] = (char *) malloc(sizeof(char) * m);
return arr;
}
/**
* first we will check if the count + 1 equal the size and if true we will create new array with a size
* of size*2 and then move all the words to the new array, if it does not equal then we will copy the new word to the
* array, also the array is passed by pointer so any change on this array in this scope it will change in the main.
* #param words the words array that has all the words
* #param newWord the new word to be inserted
* #param index the index to insert the nwe word
* #param size the size of the current array
* #param wordSize the word size the second dimension in the array
* #return will return a 2d array.
*/
char** addNewWord(char **words, char *newWord, int index, int *size, int wordSize) {
if (index == *size) {
int newSize = *size * 2;
char **newArray = allocate(newSize, wordSize);
for (int i = 0; i < *size; i++) {
strcpy(newArray[i], words[i]);
}
strcpy(newArray[index], newWord);
*size = newSize;
return newArray;
}
strcpy(words[index], newWord);
return words;
}
void print(char **words, int n) {
printf("List of words: \n");
for (int i = 0; i < n; i++) {
printf("%s\n", words[i]);
}
}
int main() {
int size = 5;
char **words = allocate(size, MAX_WORD_SIZE);
char input[MAX_WORD_SIZE];
int index = 0;
while (1) {
fgets(input, MAX_WORD_SIZE, stdin);
input[strcspn(input,"\n")] = 0;
if (strcmp("end", input) != 0) {
words = addNewWord(words, input, index, &size, MAX_WORD_SIZE);
index++;
} else {
break;
}
}
print(words, index);
return 0;
}
the way i did it is i have created a new function that is used to add the new word and if the index is equal the size of the array i have created a new array and copied the content of the first one to the second and this function will return the words array either the same array or the new one, also i have passed the size variable using pointer so i can change it in the function and this change will also change in the main.
--EDIT : i have changed the print from print(words,size) to print(words,index)
--EDIT 2: changed scanf() to fgets as it is much safer, thanks for chux - Reinstate Monica on the note, here is why scanf is dangerous.

Storing input from user as char array C | segmentation fault error

I am trying to take input from user and store it as a char array. I have the following code in which the function array, returns the address to the character array. However, I am getting a core dump error, what is happening here?
//reading and storing input from user as char array
int * array(int * r){
int ch;
int i;
r[10];
printf("enter your name: ");
for ( i = 0; i < 10; i++){
r[i] = getc(stdin);
printf("%c", r[i]);
}
return r;
}
//main
int main(void){
int *p;
p = array(p);
}
I'll try to be similar to your code.
The array could be char, instead of int and many other things (you may pass len instead of hard-coding length etc). Anyway the major error was passing a pointer without initializing it: statically as I've done, 11 places, one is for null character; or dynamically using malloc.
The if statement is just for exiting the loop if someone press enter or the stream ends, I think it's your desired behavior.
#include <string.h>
#include <stdio.h>
//reading and storing input from user as char array
void array(int * r){
int ch;
int i;
//r[10];
printf("enter your name: ");
for ( i = 0; i < 10; i++){
int ch = getc(stdin);
if ( ch == EOF || ch == '\n' || ch == '\r')
break;
r[i] = ch;
printf("%c", r[i]);
}
r[i] = 0;
}
//main
int main(void){
int p[11];
array(p);
printf("\nExit\n");
}

Adding strings to 2D array in C

I'm trying to write a program that looks for the first empty space in a 2D array and adds a custom string to that space. I have tried some things that i found on the internet but none seem to work or match my specific scenario. This is it:
#include <stdio.h>
#include <string.h>
int tags[10] = {1,2,3,4,5};
char owners[10][10] = {"per1", "per2", "per3", "per4", "per5"};
int tagAdd;
char ownerAdd;
int i;
int addBool;
int j;
int len;
int main()
{
printf("Enter the tag ID you want to add: ");
scanf("%d", &tagAdd);
printf("Enter the tag owners name: ");
scanf("%d", &ownerAdd);
len = strlen(ownerAdd);
while (i<10)
{
if (tags[i] == 0)
{
tags[i] = tagAdd;
owners[i][len] = ownerAdd; //This is the part I can't figure out
addBool = 1;
}
if (addBool == 1)
{
break;
}
i++;
}
i = 0;
addBool = 0;
len = 0;
while (i<10)
{
printf("tag[%d]", tags[i]);
len = strlen(owners[i]);
printf(" is owned by ");
while (j < len)
{
printf("%c", owners[i][j]);
j++;
}
printf("\n\r");
i++;
j = 0;
}
}
You cannot do this:
char ownerAdd;
scanf("%d", &ownerAdd);
len = strlen(ownerAdd);
You are passing the incorrect types. ownerAdd is a single char, scanf
expects with %d a pointer to int, you are passing a pointer to char and if
scanf converts the value, it will overflow. And strlen expects a char*
which points to a valid string (0-terminated). You are doing all this wrong.
This would be correct:
char ownerAdd[100];
scanf("%99s", ownerAdd);
len = strlen(ownerAdd);
And for replacing a value:
owners[i][len] = ownerAdd; //This is the part I can't figure out
is also wrong, because owners[i] is a char[10], you have to do:
strncpy(owners[i], ownerAdd, sizeof owners[i]);
owners[i][sizeof(owners[i]) - 1] = 0;
to copy the string.
The next error is that you don't initialize i and do (the first loop)
while (i<10)
{
...
}
this is going to fail. Same thing with j, it is uninitialized.

How to count a specific character in an array and also call the function?

I am trying to make a program to count a specific character in an array. I got the program working how I think it should be working, however it was all in my main function and I wanted to break it out of there but I seem to be having an issue with doing so. My code when it was all in main was:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char array[100];
int i = 0;
int a_counter = 0;
printf("Enter an array: \n");
scanf("%[^\n], array);
printf("Array is: %s\n", array);
for( i = 0; array[i] != '\0'; i++)
{
if (array[i] == 'A')
a_counter++;
}
printf("Number of A's: %d\n, a_counter);
}
In the code above, if I enter AAABCDEF, the result would tell me that there are 3 A's.
Now, I want to get this out of main and also not limit the character to only being an 'A'. I wanted to to count whatever character I set the function call with. My attempt to do so was this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char array[100];
printf("Enter an array: \n");
scanf("%[^\n], array);
printf("Array is: %s\n", array);
countletter(array, 'A');
countletter(array, 'L'); //I want to call function and add
//whatever letter I felt like it
return 0;
}
void countletter(char(array), char x)
{
int i = 0;
int count = 0;
for (i = 0; array[&i] != '\0'; i++)
if(array[&i] == x)
count++;
printf("Number of %c's: %d\n", x, count);
}
so if I called the countletter function, I wanted it to count the specific letter I sent it to count but my outputs were not even close. My outputs seemed to always be zero, and if I entered a specific array, it would put me in an infinite input mode. It seems that I am still confused on pointers and passing and calling functions.
The function you have written is wrong
void countletter(char *array, char x)
{
int i = 0;
int count = 0;
for (i = 0; array[i] != '\0'; i++)
if(array[i] == x)
count++;
printf("Number of %c's: %d\n", x, count);
}
Also before main, you have to declare the function
void countletter(char *array, char x);
Instead of defining
void countletter(char(array), char x)
{
int i = 0;
int count = 0;
for (i = 0; array[&i] != '\0'; i++)
if(array[&i] == x)
count++;
printf("Number of %c's: %d\n", x, count);
}
you should define:
void countletter(char array[], char x) // OR void countletter(char* array, char x)
{
int i = 0;
int count = 0;
for (i = 0; array[i] != '\0'; i++)
if(array[i] == x)
count++;
printf("Number of %c's: %d\n", x, count);
}
Moreover its a good practice to always pass size with an array or string. So probably below is the better function prototype.
void countletter(char array[], int size, char x)
There are two errors int he code:
void countletter(char(array), char x)
and
for (i = 0; array[&i] != '\0'; i++)
if(array[&i] == x)
The correct lines are:
void countletter(char* array, size_t size, char x)
and
for (i = 0; (i < size) && (array[i] != '\0'); i++)
if(array[i] == x)
You have to pass the entire array (by passing pointer to its first element in my example) and you have to work as usual (exactly as you did in the first monolithic version).
You must also pass the array size and take it into account when working with the array.
I would personally prefer this syntax for dealing with pointers.
void countLetter(char *array, char x) {...}
And for iterating through the array
for(i=0; *(array+i) != '\0'; i++)
Similarly for comparing
if(*(array+i) == x)
Internally, array[i] gets converted in *(array+i), so you can choose whatever you want.
The problem with your code is your method
countletter(char(array), char x)
This method is expecting two characters as parameters, where as you are passing a pointer and a character.
Second one is
array[&i]
For accessing ith element of an array, you should use something like array[i].

Printing Array of Strings

I'm parsing a text file:
Hello, this is a text file.
and creating by turning the file into a char[]. Now I want to take the array, iterate through it, and create an array of arrays that splits the file into words:
string[0] = Hello
string[1] = this
string[2] = is
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "TextReader.h"
#include <ctype.h>
void printWord(char *string) {
int i;
for (i = 0; i < strlen(string); i ++)
printf("%c", string[i]);
printf("\n");
}
void getWord(char *string) {
char sentences[5][4];
int i;
int letter_counter = 0;
int word_counter = 0;
for (i = 0; i < strlen(string); i ++) {
// Checks if the character is a letter
if (isalpha(string[i])) {
sentences[word_counter][letter_counter] = string[i];
letter_counter++;
} else {
sentences[word_counter][letter_counter + 1] = '\0';
word_counter++;
letter_counter = 0;
}
}
// This is the code to see what it returns:
i = 0;
for (i; i < 5; i ++) {
int a = 0;
for (a; a < 4; a++) {
printf("%c", sentences[i][a]);
}
printf("\n");
}
}
int main() {
// This just returns the character array. No errors or problems here.
char *string = readFile("test.txt");
getWord(string);
return 0;
}
This is what it returns:
Hell
o
this
is
a) w
I suspect this has something to do with pointers and stuff. I come from a strong Java background so I'm still getting used to C.
With sentences[5][4] you're limiting the number of sentences to 5 and the length of each word to 4. You'll need to make it bigger in order to process more and longer words. Try sentences[10][10]. You're also not checking if your input words aren't longer than what sentences can handle. With bigger inputs this can lead to heap-overflows & acces violations, remember that C does not check your pointers for you!
Of course, if you're going to use this method for bigger files with bigger words you'll need to make it bigger or allocate it dymanically.
sample that do not use strtok:
void getWord(char *string){
char buff[32];
int letter_counter = 0;
int word_counter = 0;
int i=0;
char ch;
while(!isalpha(string[i]))++i;//skip
while(ch=string[i]){
if(isalpha(ch)){
buff[letter_counter++] = ch;
++i;
} else {
buff[letter_counter] = '\0';
printf("string[%d] = %s\n", word_counter++, buff);//copy to dynamic allocate array
letter_counter = 0;
while(string[++i] && !isalpha(string[i]));//skip
}
}
}
use strtok version:
void getWord(const char *string){
char buff[1024];//Unnecessary if possible change
char *p;
int word_counter = 0;
strcpy(buff, string);
for(p=buff;NULL!=(p=strtok(p, " ,."));p=NULL){//delimiter != (not isaplha(ch))
printf("string[%d] = %s\n", word_counter++, p);//copy to dynamic allocate array
}
}

Resources