C Input scanf() confusion - c

I want to use scanf() to read the input string.
If the input of printf("Enter start word: "); is the symbol #, it will not execute the next printf("Enter end word: "); command, and if the input is a word, then it will execute the next command. But I don't know how to determine whether the input is a symbol or a word.
Whatever I input, it still executes printf("Enter end word: ");
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#define MAX_WORD_LENGTH 32
#define FORMAT_STRING "%31s"
#define VERY_HIGH_VALUE 999999
char **InputWords(int *n, char *start, char *end) {
printf("Enter a number: ");
scanf("%d", n); // the number of the input words
char **words = malloc(sizeof(char *) * *n);
assert(words != NULL);
for (int i = 0; i < *n; i++) {
// allocate memory for the length of each input word
words[i] = malloc(sizeof(char) * MAX_WORD_LENGTH);
assert(words[i] != NULL);
printf("Enter a word: ");
scanf(FORMAT_STRING, words[i]);
}
printf("Enter start word: ");
if (scanf("%s", start) == 1) {
printf("Enter end word: ");
scanf("%s", end);
};
printf("\n");
printf("%d, %s, %s", *n, start, end);
return words;
}
int main(void) {
int n;
char start, end; //the start/end word, which is not necessary in stage 1-4
char **words = InputWords(&n, &start, &end); //create an array to store all input words
return 0;
}
Moreover, when I add the code printf("%d", n); at the end of the function, the value of n becomes 0, although my input n is other number.
When I add printf("%d, %s, %s", *n, start, end); at the last, the output shows
Enter a number: 3
Enter a word: bad
Enter a word: ban
Enter a word: dad
Enter start word: bad
Enter end word: ban
110, an, ban
But in my input, the n = 3, start = ban and end = ban

There are multiple problems in the code:
you pass the addresses of single char variables to InputWords instead of arrays of sufficient length. Reading a string into single char variables causes undefined behavior because scanf() will store at least 2 bytes into the destination array.
you should always specify the maximum number of characters to store into the destination arrays for scanf("%s", ...)
to prevent reading the end word you can simply test if the word read for start starts with a #:
*end = *start = '\0';
if (scanf("%31s", start) == 1 && *start != '#') {
printf("Enter end word: ");
scanf("%31s", end);
}
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#define MAX_WORD_LENGTH 31
#define FORMAT_STRING "%31s"
char **InputWords(int *np, char *start, char *end) {
int n = 0;
*np = 0;
*start = *end = '\0';
printf("Enter a number: ");
if (scanf("%d", &n) != 1) // the number of the input words
return NULL;
char **words = calloc(sizeof(char *), n);
assert(words != NULL);
for (int i = 0; i < n; i++) {
// allocate memory for the length of each input word
words[i] = calloc(sizeof(char), MAX_WORD_LENGTH + 1);
assert(words[i] != NULL);
printf("Enter a word: ");
if (scanf(FORMAT_STRING, words[i]) != 1) {
/* invalid input or premature end of file */
while (i --> 0) {
free(words[i]);
}
free(words);
return NULL;
}
}
printf("Enter start word: ");
if (scanf(FORMAT_STRING, start) == 1 && *start != '#') {
printf("Enter end word: ");
scanf(FORMAT_STRING, end);
}
printf("\n");
printf("%d, %s, %s\n", n, start, end);
*np = n;
return words;
}
int main() {
int n;
char start[MAX_WORD_LENGTH + 1]; // the start word
char end[MAX_WORD_LENGTH + 1]; // the end word, which is not necessary in stage 1-4
char **words = InputWords(&n, start, end); //create an array to store all input words
return 0;
}

Try this and tell me what doesn't work now:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define FORMAT_STRING "%31s"
#define MAX_WORD_LENGTH 32
char **InputWords(int *n, char *start, char *end) {
printf("Enter a number: ");
scanf("%d", n); // the number of the input words
char **words = malloc((*n) * sizeof(*words));
assert(words);
for (int i = 0; i < *n; i++) {
// allocate memory for the length of each input word
words[i] = malloc(MAX_WORD_LENGTH);
assert(words[i]);
printf("Enter a word: ");
scanf(FORMAT_STRING, words[i]);
}
printf("Enter start word: ");
if (scanf(FORMAT_STRING, start) == 1) {
printf("Enter end word: ");
scanf(FORMAT_STRING, end);
};
printf("\n%d, %s, %s", *n, start, end);
return words;
}
int main(void){
int n;
char start[MAX_WORD_LENGTH];
char end[MAX_WORD_LENGTH];
char **words = InputWords(&n, start, end); //create an array to store all input words
// silence unused variables
(void) n;
(void) start;
(void) end;
return 0;
}

Related

Scanf doesnt take more than 4 characters in a const char array - C

I have a really weird bug. If I write a name which contains more than 4 characters, the printf will only output the first 4 characters.
Important note: I am not allowed to use any other library than stdio.h and I am not allowed to use anything else than scanf for input and printf for output. Moreover I am not allowed to modify the paramater list of the functions and I have to use const char. The code runs on putty via ssh on a unix system.
My code and the input/output are below. In addition, the while loop has a bug too ._.
#include <stdio.h>
int searchCharacters(const char*, char);
int getLength(const char*);
int main() {
char yesNo;
int end = 0;
const char name[] = {""};
printf("please enter a name: ");
scanf("%s", name);
int length = getLength(name);
printf("\n%s has a length of %i", name, length);
fflush(stdin);
while(end != 1) {
printf("\n\nWould you like to search a character in %s (y / n)?", name);
scanf(" %c", &yesNo);
switch(yesNo) {
case 'y':
printf("\nPlease enter a character: ");
char searchingCharacter;
scanf("%c", &searchingCharacter);
int numberOfCharacters = searchCharacter(name, searchingCharacter);
printf("\nThe letter %c is %i-times", searchingCharacter, numberOfCharacters);
break;
case 'n':
printf("\nGood bye!");
end++;
break;
}
}
return 0;
}
int searchCharacter(const char s[], char c) {
int numberOfIterations = getLength(s);
int numberOfCharacters = 0;
int i;
for (int i = 0; i < numberOfIterations; i++) {
if (s[i] == c) {
numberOfCharacters++;
}
}
return numberOfCharacters;
}
int getLength(const char s[]) {
int i = 0;
while(s[i++]);
return (i - 1);
}
Input/Output:
please enter a name: abcdefg
abcd has a length of 7 characters.
Would you like to search a character in abcd (y / n)? y
<-------------- AUTOMATIC/BUG WHILE LOOP --------------------------->
Please enter a character:
The letter
is 0-times.
</--------------AUTOMATIC/BUG WHILE LOOP---------------------------->
Would you like to search a character in abcd (y / n)? n
Good bye!
So, here is a possible answer:
"Change const char name[] to char name[100]" (from #kaylum)
"Change scanf("%c", &searchingCharacter) --> scanf(" %c", %searchingCharacters) to consume new line in input stream" (from #user3121023)
Here is the full code:
#include <stdio.h>
int searchCharacters(const char*, char);
int getLength(const char*);
int main() {
char yesNo;
int end = 0;
char name[100]; <-- Changed -->
printf("please enter a name: ");
scanf("%99s", name);
fflush(stdin);
int length = getLength(name);
printf("\n%s has a length of %i", name, length);
while(end != 1) {
printf("\n\nWould you like to search a character in %s (y / n)?", name);
scanf("%c", &yesNo); <-- Changed -->
switch(yesNo) {
case 'y':
printf("\nPlease enter a character: ");
char searchingCharacter;
scanf(" %c", &searchingCharacter); <-- Changed -->
int numberOfCharacters = searchCharacter(name, searchingCharacter);
printf("\nThe letter %c is %i-times", searchingCharacter,
numberOfCharacters);
break;
case 'n':
printf("\nGood bye!");
end++;
break;
}
}
return 0;
}
int searchCharacter(const char s[], char c) {
int numberOfIterations = getLength(s);
int numberOfCharacters = 0;
int i;
for (int i = 0; i < numberOfIterations; i++) {
if (s[i] == c) {
numberOfCharacters++;
}
}
return numberOfCharacters;
}
int getLength(const char s[]) {
int i = 0;
while(s[i++]);
return (i - 1);
}
Input/Output:
please enter a name: abcdefg
abcdefg has a length of 7 characters. <-- Working/Changed -->
Would you like to search a character in abcd (y / n)? y
Please enter a character: a <-- Working/Changed -->
The letter a is 1-times. <-- Working/Changed -->
Would you like to search a character in abcdefg (y / n)? n
Good bye!

Properly buffering and validating string

I am getting a bit of an error in my program, it is somewhat basic but here is my error: I am trying to properly input a series of strings into a structure and it seems like user input is ending at the wrong spot.
#include <stdio.h>
#include <string.h>
#define buffer 256
struct Fisher
{
char SSN[8]; //9 digit max
char First_Name[12];
char Last_Name[15];
char Phone[10];
char Email[35];
}typedef Fisher;
void getFisher(Fisher* pfisher, int i);
void dispFisher(Fisher* pfisher, int i);
void Fisherman_Menu(Fisher* pfisher, int i);
int main()
{
int i = 0;
Fisher fisherarray[3];
Fisher* pfisher = &fisherarray[0];
Fisherman_Menu(pfisher, i);
return 0;
}
void Fisherman_Menu(Fisher* pfisher, int i)
{
for(;;)
{
fflush(stdin);
printf("-1-Register Fisherman\n");
printf("-2-Search Fisherman\n");
printf("-3-Go back to Main Menu\n");
fflush(stdin);
int choice=0;
scanf(" %d", &choice);
if (choice == 1)
{
fflush(stdin);
getFisher(pfisher, i);
i++;
}
if (choice == 2)
{
fflush(stdin);
dispFisher(pfisher, i);
}
else if (choice == 3)
{
break; /* Break out of loop */
}
else
printf("Anything else?\n");
}
/* When this function returns, you get back to the main menu */
}
void getFisher(Fisher* pfisher, int i)
{
char input[buffer];
char* pinput = NULL;
//===============================
printf("Enter Social Security Number: ");
pinput = fgets(input, buffer, stdin);//validate
strcpy((pfisher+i)->SSN, pinput);
//(pfisher+i)->SSN = atoi(pinput);
//==============================
printf("Enter first name: ");
pinput = fgets(input, buffer, stdin);//validates name
strcpy((pfisher+i)->First_Name, pinput);
//==============================
printf("Enter last name: ");
pinput = fgets(input, buffer, stdin);//validates name
strcpy((pfisher+i)->Last_Name, pinput);
//==============================
printf("Enter phone number as a 10 digit number (without any
dashes or spaces): ");
pinput = fgets(input, buffer, stdin);//validate phone
strcpy((pfisher+i)->Phone, pinput);
//(pfisher+i)->Phone = atoi(pinput);
//===============================
printf("Enter email address: ");
pinput = fgets(input, 20, stdin);//validates name
strcpy((pfisher+i)->Email, pinput);
}
void dispFisher(Fisher* pfisher, int i)
{
int len;
int pen;
printf("ssn is equal to: %s\n", ((pfisher+0)->SSN));
printf("First Name is equal to: %s\n", ((pfisher+0)->First_Name));
printf("ssn is equal to: %s\n", ((pfisher+1)->SSN));
printf("First Name is equal to: %s\n", ((pfisher+1)->First_Name));
len = strlen(((pfisher+0)->SSN));
printf("string length = %d\n", len);
pen = strlen(((pfisher+1)->SSN));
printf("string length = %d\n", len);
/*
int arr = 0;
char searchSSN[9];
printf("Enter SSN: ");
scanf("%s", &searchSSN);
for(arr = 0; arr < i; arr++)
{
if(strcmp(&searchSSN, (pfisher+arr)->SSN) == 0)
{
//printf("I is equal to: %s\n", (pfisher+i)->SSN);
printf("Fisher\n");
printf("-------------------------------------------\n");
printf("%d \n %s \n %s \n %s \n %s ", (pfisher + arr)->SSN, ((pfisher+arr)->First_Name), ((pfisher+arr)->Last_Name), ((pfisher+arr)->Phone), (pfisher+arr)->Email);
printf("-------------------------------------------\n");
}
}
*/
}
My output for SSN is getting messed up and becoming "123456789(FirstName string)
example: 123456789TurboTurkey
How can I clean up the length of the string and get in the SSN properly
There is no enough space to store 9 digit in SSN. If you want to store 9 digit in it, its size should be 10 (9 digit + NULL). If there is no NULL charactor, it will read near by locations too..

Why I can't input my name with gets?

Here's the part of my code:
Problem: It skips the input of "please enter your name" to "please enter your marks"
What I tried: flushall(); _flushall(); - which worked yesterday somehow, and trying to place these functions between printf,scanf..
student *Create_Class(int size) {
int i, j;
int idStud, nameStud, markStud;
student *classStudent;
classStudent = (student*)malloc(size * sizeof(student));
for (i = 0; i < size; i++) {
classStudent[i].name = (char*)malloc(51 * sizeof(char));
int numOfmarks = 4;
printf("Please enter your name: ");
gets(classStudent[i].name);
_flushall(); //tried _flushall() and it worked yesterday.. tried fflush(NULL) too.
printf("\nPlease enter 4 marks: ");
for (j = 0; j < numOfmarks; j++) {
scanf("%d", &classStudent[i].marks[j]);
}
Avg_Mark(&classStudent[i]);
}
return classStudent;
}
EDIT: (FULL CODE)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
typedef struct {
char *name;
int marks[4];
float avg;
} student;
student *Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void exStudents(student *s, int size);
int main() {
int size, i;
student *arr;
printf("\nEnter the number of students: \n");
scanf("%d", &size);
arr = Create_Class(size);
exStudents(arr, size);
for (i = 0; i < size; i++)
free(arr[i].name);
free(arr);
getch();
}
student *Create_Class(int size) {
int i, j;
int idStud, nameStud, markStud;
student *classStudent;
classStudent = (student*)malloc(size * sizeof(student));
for (i = 0; i < size; i++) {
classStudent[i].name = (char*)malloc(51 * sizeof(char));
int numOfmarks = 4;
int sizeOfName;
printf("Please enter your name: \n");
_flushall();
fgets(classStudent[i].name,50,stdin);
sizeOfName = strlen(classStudent[i].name);
printf("Please enter 4 marks: ");
for (j = 0; j < numOfmarks; j++) {
scanf("%d", &classStudent[i].marks[j]);
}
Avg_Mark(&classStudent[i]);
}
return classStudent;
}
void Avg_Mark(student *s) {
int i, numOfMarks = 4, sum = 0;
for (i = 0; i < numOfMarks; i++) {
sum += s->marks[i];
}
s->avg = (sum / 4.0);
}
void Print_One(student *s) {
printf("The average of %s is %f", s->name, s->avg);
}
void exStudents(student *s, int size) {
int flag = 1;
while (size > 0) {
if (s->avg > 85) {
Print_One(s);
flag = 0;
}
s++;
size--;
}
if (flag)
printf("\n There're no students with above 85 average.");
}
As you have already been told in comments, the solution is to use a two-step approach: Read lines first, then scan these lines as appropriate. This reflects how users are going to answer your prompts, namely by providing the information and then hitting enter.
Here's a variant of your code which does that. I've also changed the main function, because it also used scanf and I've added a function to strip white space from the string input by fgets. (This function requires the <ctype.h> header.)
#include <ctype.h>
int main()
{
char line[80];
int size, i;
puts("Enter the number of students:");
if (fgets(line, sizeof(line), stdin) == NULL) exit(1);
if (sscanf(line, "%d", &size) == 1 && size > 0) {
student *arr = Create_Class(size);
exStudents(arr, size);
for (i = 0; i < size; i++) free(arr[i].name);
free(arr);
}
return 0;
}
/*
* strip white space from beginning and end of string
*/
char *strip(char *str)
{
size_t l = strlen(str);
while (l > 0 && isspace((unsigned char) str[l - 1])) l--;
str[l] = '\0';
while (isspace((unsigned char) *str)) str++;
return str;
}
/*
* Create students and prompt user for input
*/
student *Create_Class(int size)
{
int i;
student *classStudent = malloc(size * sizeof(student));
for (i = 0; i < size; i++) {
char line[80];
char *p;
int okay = 0;
puts("Please enter your name:");
if (fgets(line, sizeof(line), stdin) == NULL) exit(1);
p = strip(line);
classStudent[i].name = malloc(strlen(p) + 1);
strcpy(classStudent[i].name, p);
while (!okay) {
int j = 0;
okay = 1;
puts("Please enter 4 marks:");
if (fgets(line, sizeof(line), stdin) == NULL) exit(1);
p = line;
while (p && j < 4) {
char *tail;
int m = strtol(p, &tail, 10);
if (p == tail) break;
if (m < 1 || m > 100) {
puts("Illegal mark.");
okay = 0;
}
classStudent[i].marks[j++] = m;
p = tail;
}
if (j < 4) {
printf("Expected 4 marks, but got %d.\n", j);
okay = 0;
}
}
Avg_Mark(&classStudent[i]);
}
return classStudent;
}
Please refrain from flushing buffers wihout reason. When a new-line character is written, stdout is flushed, so make it a rule to terminate all your strings with a new-line. New-lines at the beginning of strings instead of at the end are a sign of untidy output.
SOLUTION:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
typedef struct { //struct decleration
char *name;
int marks[4];
float avg;
} student;
//functions decleration
student *Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void exStudents(student *s, int size);
int main() {
/*variable declerations*/
int i, size;
char line[80];
student *arr;
/*Input number of students*/
printf("\nEnter the number of students: \n");
fgets(line, sizeof(line), stdin);
sscanf(line, "%d", &size);
/*Get name of students, marks, and calculate average above 85*/
arr = Create_Class(size);
exStudents(arr, size);
/*Free memory*/
for (i = 0; i < size; i++)
free(arr[i].name);
free(arr);
getch();
}
student *Create_Class(int size) { /*Get names of each student, and their 4 marks.*/
/*Variable declerations*/
int i, j;
char line[51];
student *classStudent;
/*Dynamic allocation to assign structure to every student*/
classStudent = (student*)malloc(size * sizeof(student));
/*Get name of students and their 4 marks*/
for (i = 0; i < size; i++) {
/*Variable decleration and dynamic allocation of 51 chars*/
classStudent[i].name = (char*)malloc(51 * sizeof(char));
int numOfmarks = 4;
int sizeOfName;
/*Input name of student*/
printf("Please enter your name: \n");
scanf("%s", classStudent[i].name);
/*Input marks of student*/
printf("Please enter 4 marks: ");
for (j = 0; j < numOfmarks; j++) {
scanf("%d", &classStudent[i].marks[j]);
}
/*Calculate average, and print averages of students above 85*/
Avg_Mark(&classStudent[i]);
}
return classStudent;
}
/*Calculate averages of students*/
void Avg_Mark(student *s) {
int i, numOfMarks = 4, sum = 0;
for (i = 0; i < numOfMarks; i++) {
sum += s->marks[i];
}
s->avg = (sum / 4.0);
}
/*Print average (if bigger than 85)*/
void Print_One(student *s) {
printf("The average of %s is %0.1f\n", s->name, s->avg);
}
/*Check whether the average is bigger than 85*/
void exStudents(student *s, int size) {
int flag = 1; //flag to check if there are any students with avg above 85
while (size > 0) {
if (s->avg > 85) {
Print_One(s); //Print the average
flag = 0; //We found atleast one student with avg > 85
}
s++; //Advance to next student
size--;
}
if (flag)
printf("\n There're no students with above 85 average.");
}
The problem in your code is that scanf does not consume the new-line returned by the user in:
scanf("%d", &size);
So when the program reaches:
fgets(classStudent[i].name,50,stdin);
the remaining new-line in stdin is received before the user can type anything.
A solution is to replace the initial scanf call by fgets and atoi calls.
char size_str[5];
fgets(size_str,5,stdin);
size = atoi(size_str);
A combination of fgets and sscanf also works also fine in general to first process user inputs and then convert it.
The variant with sscanf is:
char size_str[5];
fgets(size_str,5,stdin);
sscanf(size_str,"%d\n",&size);
Note that it might be safe to stop the program if the value entered is too large. Here we allow from 0 up to 999.
Note also that you have to do the same change some lines below.
instead of:
scanf("%d", &classStudent[i].marks[j]);
write:
char mark_str[5];
fgets(mark_str,5,stdin);
sscanf(mark_str,"%d\n",&classStudent[i].marks[j]);
Hope this helps.

Arrays in a Palindrome program

So I made a program where I have to input a word and it displays if it is a palindrome (a word that is the same both ways) or not.
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[]){
char word;
int length, counter;
printf("Please enter a word: ");
scanf("%c", &word);
int flag = 1;
for (counter = 0; counter < length && flag; counter++) {
printf("%c\t %c", word[counter], word[length - counter])
if (word[counter] == word[length - counter - 1]){
flag = 0;
}
}
if (flag) {
printf("%c is a palindrome!", word);
}
else {
printf("%c is NOT a palindrome!", word);
}
}
I set it up so that it displays each letter side by side. If a letter isn't the same then the flag is "thrown"(set to 0) and this will end the program saying: "word is NOT a palindrome!"
I get an error at the part where it says word[counter] saying it isn't a subscripted value. What can I do to make this work? Is there anything else I am doing wrong?
This char word; is not an array. This char word[100]; is an Array. Also you read a single character using scanf("%c", &word); not a word (as in a string or series of characters). Use:
fgets (word , 100 , stdin)
Also length is not initialized, so it will lead to UB.
Make this modifications in your program.It will run fine.
#include <stdio.h>
#include <string.h>
int main()
{
char word[100];
int length, counter;
printf("Please enter a word: ");
scanf("%s",word);
length=strlen(word);
int flag = 1;
for(counter = 0; counter < length/2 && flag; counter++)
{
if (word[counter] != word[length-counter-1])
{
flag = 0;
break;
}
}
if (flag)
{
printf("%s is a palindrome!\n", word);
}
else {
printf("%s is NOT a palindrome\n!", word);
}
}
****************************************************************
* Simple Array Palindrome Program *
****************************************************************/
#include <iostream>
using namespace std;
int main (){
int arr_size;
int flag=0;
/*****************************************
* Array Size *
*****************************************/
cout<<"Enter The Array Size: \n->arr[";
cin>>arr_size;cout<<" ]";
int arr[arr_size];
/*****************************************
* User_Input *
*****************************************/
for(int i=0;i<arr_size;i++){
cout<<"Enter Value For Arr[ "<<i<<" ] -> ";
cin>>arr[i];
}
/*****************************************
* Palindrome_Check *
*****************************************/
for(int k=0,j=arr_size-1;k<arr_size && j>-1;k++)
{
if(arr[i]==arr[j];
{
flag++;
}
}
/*****************************************
* Flag Check *
*****************************************/
if(flag==arr_size) {
cout<<"Array Is Palindrome: ";
}
else
{
cout<<"Array Is Not Palindrome: ";
}
}

Dynamic Memory Allocation

I'm having trouble dynamically allocating memory for an array. I've been debugging for hours, any pointers?
I posted the rest of the code. It is simply supposed to exchange the swap the first row with the second, and the third with the forth. I am getting strange results like:
Enter string: hello
Enter string: how are you
Enter string: i'm good thanks
Enter string: bye
Enter string: bai
Enter string: xx
=========================
how are you
!i'm good thanks
hello
!how are you
bye
!bai
i'm good thanks
!bye
bai
!xx
int count = 0;
char *lines[MAX_LINES];
char *tmp[50];
printf("Enter string: ");
fgets(tmp, 50, stdin);
lines[count] = (char *) malloc((strlen(tmp)+1) * sizeof(char));
strcpy(lines[count], tmp);
while(strcmp("xx\n", lines[count])){
count++;
printf("Enter string: ");
fgets(tmp, 50, stdin);
lines[count] = (char *) malloc((strlen(tmp)+1)* sizeof(char));
strcpy(lines[count], tmp);
}
void exchange(char * records[])
{
char * temp;
temp = records[0];
records[0] = records[1];
records[1] = temp;
temp = records[2];
records[2] = records[3];
records[3] = temp;
}
void printArray(char * inputs[], int row, int col)
{
int i, j;
for(i = 0; i < row; i++){
for(j = 0; j < col; j++){
printf("%c", inputs[i][j]);
}
}
}
This code seems to work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAX_LINES = 50 };
static void printArray(char *inputs[], int rows);
static int readLine(char *buffer, size_t buflen);
int main(void)
{
int count = 0;
char *lines[MAX_LINES];
char tmp[50];
for (count = 0; count < MAX_LINES; count++)
{
if (readLine(tmp, sizeof(tmp)) == EOF)
break;
lines[count] = (char *) malloc((strlen(tmp)+1)* sizeof(char));
if (lines[count] == 0)
break;
strcpy(lines[count], tmp);
}
putchar('\n');
printArray(lines, count);
return(0);
}
static int read_line(char *buffer, size_t buflen)
{
printf("Enter string: ");
if (fgets(buffer, buflen, stdin) == 0 || strcmp("xx\n", buffer) == 0)
return EOF;
return 0;
}
static void printArray(char *inputs[], int rows)
{
for (int i = 0; i < rows; i++)
printf("%d: %s", i, inputs[i]);
}
Sample run 1 (using EOF):
$ ./rl
Enter string: Abyssinia
Enter string: Wimbledon Common
Enter string: ^D
0: Abyssinia
1: Wimbledon Common
$
Sample run 2 (using 'xx'):
$ ./rl
Enter string: Abyssinia
Enter string: Wimbledon Common
Enter string: Strawberry Lemonade
Enter string: xx
0: Abyssinia
1: Wimbledon Common
2: Strawberry Lemonade
$
What's different? I fixed the type on tmp as noted in a comment. I created a function readLine() to manage the prompt and read and compare with "xx\n" process to avoid repetition. I avoided using strdup() but do check that malloc() succeeds before using the pointer returned. I ensure that there are not too many lines read in (the for loop). The printArray() code only takes the number of rows because the strings are of varying length. I removed the exchange() function since it was not being used and I couldn't see how it was supposed to be used. The code is complete and compilable (so it is an SSCCE — Short, Self-Contained, Correct Example).

Resources