Why doesn't my C program wait to scan input? - c

I am new to C. I allocated memory with this statement:
patientptr = (char*) calloc (118, sizeof (char));
then I assign data using this (this is a part of the function):
char name[51];
int age;
char agestr[3];
char infectiondate [11];
char address[51];
char *patientptr;
printf("\nEnter the patient name (50 characters at maximum): ");
scanf ("%50s", name);
*patientptr = name;
printf("Enter the patient age: ");
scanf ("%d", &age);
sprintf (agestr, "%2d", age);
*(patientptr + 51) = agestr;
printf("Enter the patient date of infection (in form of dd/mm/year): ");
*(patientptr + 54) = scanf ("%10d", infectiondate);
printf("Enter the patient address (50 characters at maximum): ");
*(patientptr + 65) = scanf ("%50s", address);
*(ptrsptr+patientsnum-1) = patientptr;
printf ("\nPatient added.\n");
Everything goes fine except that after the "enter the patient address: " line, it prints the "patient added" line directly without waiting to scan the address. the output is like this:
Enter the patient name (50 characters at maximum): ahmed
Enter the patient age: 20
Enter the patient date of infection (in form of dd/mm/year): 10/10/2020
Enter the patient address (50 characters at maximum):
Patient added.
is the wrong with my allocated memory?

You may well have used calloc to allocate some memory but examine this snippet:
char *patientptr;
printf("\nEnter the patient name (50 characters at maximum): ");
scanf ("%50s", name);
*patientptr = name;
That first line shadows whatever patientptr was with an uninitialised pointer, hence the final line is undefined behaviour (patientptr now points to some arbitrary address). All bets are off at this point, anything is possible.
Fix that and try again.
In addition, it looks like you believe that:
*(patientptr + 51) = agestr;
is a way to copy a C string from one place to another. In actual fact, this will attempt to place the agestr pointer value into the single character at the memory location &(patientptr[51]), and possibly should have warned you about this.
You need to look into strcpy for this, something along the lines of:
strcpy(patientptr + 51, agestr);
But, if you're looking to do user input, it's often a good idea to work around the limits of scanf. It does, after all, stand for "scan formatted" and there's very little that's less formatted than user input.
I have a favourite function I use for this, which is shown below, along with the modifications to your own code to use it (using both that function and with quite a bit of other validation specific to your case):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
// Bullet-proof line input function.
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
// Ensure a character array is non-empty and all digits.
int checkDigits(char *arr, size_t sz) {
if (sz == 0) {
return 0;
}
while (sz-- > 0) {
if (! isdigit(*arr++)) {
return 0;
}
}
return 1;
}
// Get customer data line, return NULL if okay, error if not.
// Output record must be long enough for format string below
// and a one-character end-string marker.
static char *getPatientData(char *patientData) {
// Keep this format string in sync with field sizes below.
static char *fmtString = "%-50.50s" "%3d" "%-10.10s" "%-50.50s";
char name[51];
char ageStr[4];
char infectionDate[11];
char address[51];
if (getLine("Patient name: ", name, sizeof(name)) != OK) {
return "Error getting name.";
}
if (getLine("Patient age: ", ageStr, sizeof(ageStr)) != OK) {
return "Error getting age.";
}
if (! checkDigits(ageStr, strlen(ageStr))) {
return "Error, age contains non-digit data.";
}
int age = atoi(ageStr);
// Further age sanity checking, if desired. Example: ensure <= 150.
if (getLine("Infection date (dd/mm/yyyy): ", infectionDate, sizeof(infectionDate)) != OK) {
return "Error getting infection date.";
}
if (
strlen(infectionDate) != 10
|| infectionDate[2] != '/'
|| infectionDate[5] != '/'
|| ! checkDigits(infectionDate, 2)
|| ! checkDigits(infectionDate + 3, 2)
|| ! checkDigits(infectionDate + 6, 4)
) {
return "Error, incorrect format.";
}
// Further checking if desired. Example: valid year/month/day combo.
if (getLine("Patient address: ", address, sizeof(address)) != OK) {
return "Error getting address.";
}
sprintf(patientData, fmtString, name, age, infectionDate, address);
return NULL;
}
int main(void) {
char *patientPtr = malloc (50 + 3 + 10 + 50 + 1);
char *result = getPatientData(patientPtr);
if (result != NULL) {
printf("*** %s\n", result);
return 1;
}
printf("Got '%s'\n", patientPtr);
return 0;
}
A sample run follows:
Patient name: Pax Diablo
Patient age: 55
Infection date (dd/mm/yyyy): 25/05/2020
Patient address: No fixed abode
Got 'Pax Diablo 5525/05/2020No fixed abode '

Related

Writing to file and using if statments with loops

I am creating a simple system for people to enter there basic details, have them printed on the screen and once confirmed writen to a text file, is the info is wrong the user enters edit ot be looped back to the beginning of the report and if another input is ented it asks the question again. Im a struggling to get the print to file to work and the two end loops.
#include <stdio.h>
#include <string.h>
int get_line(const char *prompt, char *dest, size_t size) {
printf("%s", prompt);
fflush(stdout);
if (fgets(dest, size, stdin) == NULL) {
dest[0] = '\0';
return 0;
}
dest[strcspn(dest, "\n")] = '\0'; // Lop off potential trailing '\n'
return 1;
}
int main(void)
{
char first_name[20], surname[20], street_no[10], street_name[40], postcode[10], contact_no[20], save_edit_qu[10];
int dd, mm, yy;
get_line(" Enter first name:\n", first_name, sizeof first_name);
get_line(" Enter surname:\n", surname, sizeof surname);
get_line(" Contact Number\n", contact_no, sizeof contact_no);
get_line(" Street Number\n", street_no, sizeof street_no);
get_line(" Street Name\n", street_name, sizeof street_name);
get_line(" Postcode\n", postcode, sizeof postcode);
printf(" First Name : %s\n", first_name);
printf(" Surname : %s\n", surname);
printf(" Contact No.: %s\n", contact_no);
printf(" Street No. : %s\n", street_no);
printf(" Stret Name : %s\n", street_name);
printf(" Postcode : %s\n", postcode);
get_line(" If the informations above is correct please enter SAVE/if you wish to change any informations please enter edit", save_edit_qu, sizeof save_edit_qu);
if (save_edit_qu[0] == 'SAVE' || save_edit_qu[0] == 'save') {
//write info to file
}
if (save_edit_qu[0] == 'EDIT' || save_edit_qu[0] == 'edit') {
//loop back to beginning of report
}
else if ()//loop to beginning of SAVE/EDIT QU
return 0;
}
use strcmp() and use double quotes "" for string !
if (strcmp(save_edit_qu,"SAVE") == 0 || strcmp(save_edit_qu,"save") == 0) {
or test only first character using single quotes like this
if (save_edit_qu[0] == 'S' || save_edit_qu[0] == 's') {
So, there are a couple of things wrong about your program. I'll try to cover them all here before I show you the changes.
Your string comparison is simple nonsensical: save_edit_qu[0] == 'SAVE' simply compares the first character/byte of save_edit_qu to 'SAVE', which itself isn't a proper string literal. You've got to enclose string literals in double quotes in C. And even if you did do that here, it doesn't make sense to compare a character to a string. What you should do is use strcmp from string.h to do the comparison for you. I've placed that inside my fixed version of your program. The format is: strcmp(a,b) == 0 if string a is equal to string b.
You're giving users the ability to edit all their input data. Therefore, you should be placing your data collection in a loop. This allows you to constantly re-collect the data as long as the user isn't done.
do {
// collect data.
} while (!done);
Finally, you're having users perform an action within the data collection loop so that they can choose what they'd like to do with the data. They can either edit, or save. There's also the case they enter neither. In this case, they'll be prompted again. This warrants another control loop inside.
do {
// collect data
do {
// save or edit
} while (!validChoice);
} while (!done);
With this said, here is the working program. I have not implemented the writing-to-file portion for you though. I think you can give that a shot yourself!
#include <stdio.h>
#include <string.h>
int get_line(const char *prompt, char *dest, size_t size) {
printf("%s", prompt);
fflush(stdout);
if (fgets(dest, size, stdin) == NULL) {
dest[0] = '\0';
return 0;
}
dest[strcspn(dest, "\n")] = '\0'; // Lop off potential trailing '\n'
return 1;
}
int main(void)
{
char first_name[20], surname[20], street_no[10], street_name[40], postcode[10], contact_no[20], save_edit_qu[10];
int dd, mm, yy, done = 0;
// Data collection loop: Runs as long as the user opts to edit the data.
do {
// Fetch data.
get_line(" Enter first name:\n", first_name, sizeof first_name);
get_line(" Enter surname:\n", surname, sizeof surname);
get_line(" Contact Number\n", contact_no, sizeof contact_no);
get_line(" Street Number\n", street_no, sizeof street_no);
get_line(" Street Name\n", street_name, sizeof street_name);
get_line(" Postcode\n", postcode, sizeof postcode);
printf(" First Name : %s\n", first_name);
printf(" Surname : %s\n", surname);
printf(" Contact No.: %s\n", contact_no);
printf(" Street No. : %s\n", street_no);
printf(" Stret Name : %s\n", street_name);
printf(" Postcode : %s\n", postcode);
// Action loop: Runs as long as no valid input is given.
do {
get_line(" If the informations above is correct please enter SAVE/if you wish to change any informations please enter edit\n", save_edit_qu, sizeof save_edit_qu);
// Option to quit.
if (strcmp(save_edit_qu, "SAVE") == 0 || strcmp(save_edit_qu, "save") == 0) {
fprintf(stdout, "Writing data to file...\n");
// write data here.
// Set done flag, and exit action loop.
done = 1;
break;
}
// Option to edit.
if (strcmp(save_edit_qu, "EDIT") == 0 || strcmp(save_edit_qu, "edit") == 0 ) {
//loop back to beginning of report
break;
}
// Otherwise ask prompt again ^.
} while (1);
} while (!done);
return 0;
}

How to enter and scan multiple chars in c

I want to enter multiple printfs but i dont get opportunity to enter.
I can enter only 1, but after that it just ends the programme.I tried with do while but it didnt work
int main()
{
int number;
char username[30]="";
char fullName[30]="";
char password[30]="";
printf("Do you want to log in(1) or register (2)? \n");
scanf("%d",&number);
if (number==2)
{
printf("username : ");
scanf("%s",&username);
printf("Full name : ");
scanf("%s",&fullName);
printf("Password : ");
scanf("%s",&password);
printf("Repeat password : ");
scanf("%s",&password);
}
return 0;
}
Read full lines using fgets() into a suitably large buffer, then parse that.
Note that %s will stop at the first blank character, so a full name of "Mr X" will leave "X" in the input buffer, grabbing that for the password and so on. It's really not a robust way of getting input.
I can enter only 1, but after that it just ends the programme.
Of course, as the code has if (number==2) #Scadge
If you enter "2", consider the following:
scanf("%s",&fullname); will not save spaces or other white-spaces into fullname. Entering a full name like "John Doe" will save "John" into fullname and "Doe" into password.
Avoid using scanf().
Rather than use scanf() to read user input, read user input with fgets(). This is a fine opportunity for helper functions that can handle various input issues.
int read_int(const char *prompt) {
if (prompt) fputs(prompt, stdout);
fflush(stdout); // insure output is written before asking for input
char buffer[40];
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
return NULL;
}
int i;
if (sscanf(buffer, "%d", &i) == 1) {
return i;
}
// TBD - what should code do if invalid data entered. Try again?
}
char *read_line(char *dest, sizeof size, const char *prompt) {
if (prompt) fputs(prompt, stdout);
fflush(stdout); // insure output is written before asking for input
char buffer[size * 2 + 1]; // form buffer at _least 1 larger for \n
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
return NULL;
}
size_t len = strlen(buffer);
if (len > 0 && buffer[len-1] == '\n') buffer[--len] = '\0';
if (len >= size) {
// input too big - how do you want to handle this?
TBD_Code();
}
return strcpy(dest, buffer);
}
Now use these 2 helper functions for clean user input
// printf("Do you want to log in(1) or register (2)? \n");
// scanf("%d",&number);
number = read_int("Do you want to log in(1) or register (2)? \n");
...
// printf("username : ");
// scanf("%s",&username);
read_line(username, sizeof username, "username : ");
// printf("Full name : ");
// scanf("%s",&fullName);
read_line(fullName, sizeof fullName, "fullName : ");
Additional code could be added to check for end-of-file, extremely long lines, int range testing, etc.
Use c library function fgets().
#include <stdio.h>
int main(){
Char username[10];
printf(“Username: “);
fgets(username,10,stdin);
}

Strings in a FOR loop

I got a question.
I want to have a FOR loop that prints back text many strings. Lets say I type my forename and last name. And a FOR loop produce the strings.
#include <stdio.h>
int main(){
char str1 [12];
char str2 [12];
char wordarray [2]={str1,str2}; // error here
int i;
printf ("Type your forname : ");
scanf ("%s",&str1);
printf ("\nType your last name : ");
scanf ("%s",&str2);
printf ("\n\nYour name is : ");
printf ("%s\t%s",str1,str2);
printf ("\n");
for (i=0;i<3;i++){
printf ("%s",wordarray [i]); // Error here .
} // end FOR
return 0;
} // end MAIN
You need to validate each read with scanf (or whatever function you use for user input) to insure you have valid data to work with. You should also provide a width limitation for the read to insure you do not read beyond the end of your array. (e.g. scanf ("%11s", str1)). You should look into using fgets for user input and remove the '\n' included by fgets in your buffer. This will help you avoid a number of pitfalls with scanf that usually plague new users, especially when taking mixed string and numeric input.
Other than that, you should also look to avoid using magic numbers in your code (e.g. char str1[12]). If you need a constant 12, then define one or declare an enum to create it.
Putting those pieces together, you could do something like:
#include <stdio.h>
#define LEN 12
int main (void) {
char str1 [LEN] = "";
char str2 [LEN] = "";
char *wordarray[] = {str1, str2};
int i, nwords = sizeof wordarray/sizeof *wordarray;
printf ("Type your forname : ");
if (scanf ("%11s", str1) != 1) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
printf ("Type your last name : ");
if (scanf ("%11s", str2) != 1) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
printf ("\nYour name is : %s %s\n", str1, str2);
for (i = 0; i < nwords; i++){
printf ("%s", wordarray [i]);
}
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/name
Type your forname : david
Type your last name : rankin
Your name is : david rankin
davidrankin
Look things over, and consider the other answers and let me know if you have further questions. Also take my comment regarding zero input or input beyond 12 characters into consideration. This will help build robustness into your input handling.
If you would like to approach the input using fgets, you can improve your input handling a bit with the following:
#include <stdio.h>
#include <string.h>
#define LEN 12
int main (void) {
char str1 [LEN] = "",
str2 [LEN] = "",
*wordarray[] = {str1, str2};
size_t i, len = 0, nwords = sizeof wordarray/sizeof *wordarray;
printf ("Type your forname : ");
if (!fgets (str1, LEN, stdin)) { /* read with fgets/validate */
fprintf (stderr, "error: invalid input.\n");
return 1;
}
len = strlen (str1); /* get length of str1 */
if (str1[len-1] == '\n') /* test for trailing '\n' */
str1[--len] = 0; /* overwrite with nulbyte */
printf ("Type your last name : ");
if (!fgets (str2, LEN, stdin)) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
len = strlen (str2);
if (str2[len-1] == '\n')
str2[--len] = 0;
printf ("\nYour name is : %s %s\n", str1, str2);
for (i = 0; i < nwords; i++){
printf ("%s", wordarray [i]);
}
putchar ('\n');
return 0;
}
You don't understand how array and pointer work. You should read this answer.
#include <stdio.h>
int main(void) {
printf("Type your forname : ");
char str1[12];
{ // we open a scope because ret don't need to be in function scope
int ret = scanf("%11s", str1); // scanf need to know how many bytes are
// available without count `\0` and you must send the array itself not the
// address
if (ret != 1) { // scanf don't set str1
fprintf(stderr, "Error in input\n"); // stderr is the error stream
return 1;
}
}
printf("\nType your last name : ");
char str2[12];
{
int ret = scanf("%11s", str2);
if (ret != 1) {
fprintf(stderr, "Error in input\n");
return 1;
}
}
printf("\n\nYour name is : ");
printf("%s\t%s", str1, str2);
printf("\n");
char *word[2] = {str1, str2}; // we need an array of pointer
for (size_t i = 0; i < sizeof word / sizeof *word; i++) { // size of array
printf("%s", word[i]);
}
return 0;
}
Shure I dont know how everything functions. That why I ask :) Thanks for the reply. I will investigate. With this information I will try to build a larger FOR-loop , so I can insert values in a 2D array. The user can add values to a 2d array then change the information text or numbers in the slots.
#include <stdio.h>
#define lenght 12 // corrected, define string format lenght
int main(){
char str1 [lenght]; // corrected, strings should have format lenght
char str2 [lenght]; // corrected, strings should have format lenght
char *wordarray [2]={str1,str2}; // corrected, add a * to wordarray[2]
int i;
printf ("Type your forname : ");
scanf ("%s",str1); // corrected, skip the & in ("%s",&str1);
printf ("Type your last name : ");
scanf ("%s",str2); // corrected, skip the & in ("%s",&str2);
printf ("\n\nYour name is : %s\t%s\n",str1,str2);
for (i=0;i<2;i++){ // corrected, i<2 must match the array elements
printf ("%s\t",wordarray [i]);
} // end FOR
return 0;
} // end MAIN
Ok. Had another go.
Havent worked much with strings. This program has both strings and numbers in arrays and printed in FOR loops. I also tried to get the indevidual elements in the arrays available to the user, so he could change the values.
I guess my style is pretty wretched. but ... its what I got.
Now concerning the GETS (str1), obtaining a string from the user. At the first use in the program it behaves normal. but the second time in the program I had to use GETS ("%s", str1) so it behaved proper. also an issue was to add specific numbers from a array detremined by the user. displayed in a for loop...
Another issue is to CLEAR the console screen after the JUMP . so the text doesnt flood the screen.
Comment : I agree David C. Rankin that validation of user data is important. Only tolerate character inputs on string requests, and numbers on integer request. Also return false input if "special characters" like slash or dots. I tried to read the origonal K&R C book and they talked about it, topics like turning all letters to small case or big case. but I had troubles getting the example code to run, maybe a C89 C11 compiler issue, I dont know.
#include <stdio.h>
//#include <string.h> // GCC32-C . mingw . compile
#define lenght 20 // Orbit_L75.Apartment_9
int main(){
int i,j,k,select,select2,*ptr;
char str1 [lenght];
char str2 [lenght];
char *wordarray [2]={str1,str2}; // character array must have a * asterix pointer .
int numarray [2];
printf ("Type your forname : ");
gets (str1); // gets (wordarray[0]) // alternative syntax
printf ("Type your last name : ");
gets (str2);
printf ("Enter your telephone number : ");
scanf ("%d",&numarray[0]); // assign a value to numarray slot 0
//scanf ("%d",(numarray+0)); // alternative syntax
printf ("Enter your age : ");
scanf ("%d",&numarray[1]); // assign a value to numarray slot 1
printf ("\n\n");
jump1 :
printf ("=========================\n");
for (i=1;i<5;i++)
{printf ("%d\t",i);}
printf ("\n");
for (j=0;j<2;j++)
{printf ("%s\t",wordarray[j]);}
//printf ("%s\t",*(wordarray+j));} // alternative syntax
printf ("\n");
for (k=0;k<2;k++)
{printf ("%d\t",numarray[k]);}
printf ("Sum = %d\n",(numarray[0]+numarray[1])); // add numarray slot 0 and slot 1.
//printf ("Sum = %d",*(numarray+0)+*(numarray+1)); // alternative syntax
printf ("=========================\n");
printf ("\n\nSelect\n1: Change Telephone \n2: Change Age \n3: Change First Name \n4: Change Last Name \n5: RAM location\n");
scanf ("%d",&select);
if (select == 1)
{printf ("New number : ");
scanf ("%d",&numarray[0]);
//scanf ("%d",(numarray+0)); // alternative syntax
printf ("\n");}
else if (select == 2)
{printf ("New age : ");
scanf ("%d",&numarray[1]);
printf ("\n");}
else if (select == 3)
{printf ("New First Name : ");
scanf ("%s",str1); //problems with the display using GETS on the second run.
printf ("\n");}
else if (select == 4)
{printf ("New Last Name : ");
scanf ("%s",str2);
printf ("\n");}
else if (select == 5)
{ // select2
{printf ("\nRAM location of : \n\t1. Telephone number\n\t2. Age\n\t3. First Name.\n\t4. Last Name\n");}
scanf ("%d",&select2);
if (select2 == 1)
{ptr = &numarray[0];
printf ("\nTelephone number\nValue in Decimal\t: %d\nValue in Hexadecimal\t: %ph\nRAM location in decimal\t: %d\nRAM location in Hex\t: %ph\n\n\n",*ptr,*ptr,ptr,ptr);}
else if (select2 == 2)
{ptr = &numarray[1];
printf ("\nAge\nValue in Decimal\t: %d\nValue in Hexadecimal\t: %ph\nRAM location in decimal\t: %d\nRAM location in Hex\t: %ph\n\n\n",*ptr,*ptr,ptr,ptr);}
else if (select2 == 3)
{ptr = &wordarray[0];
printf ("\nFirst Name\nValue in Text\t: %s\nValue in Hexadecimal\t: %ph\nRAM location in decimal\t: %d\nRAM location in Hex\t: %ph\n\n\n",*ptr,*ptr,ptr,ptr);}
else if (select2 == 4)
{ptr = &wordarray[1];
printf ("\nLast Name\nValue in Text\t: %s\nValue in Hexadecimal\t: %ph\nRAM location in decimal\t: %d\nRAM location in Hex\t: %ph\n\n\n",*ptr,*ptr,ptr,ptr);}
else if (select2 <1 || select2 > 4)
{printf ("\nValue is out of range, Try again .\n\n");}
} // end IF select2
else if (select <1 || select > 5)
{printf ("\nValue is out of range, Try again .\n\n");}
goto jump1;
return 0;
} // end MAIN
str1 and str2 are effectively pointers.
wordarray is an array of chars. It should be an array of pointers to char.
Also in your scanf you're passing address of str1 and str2, but you should just pass str1 and str2.

C string input overflows other string input

I'm doing a simple console type command system, and inputting a command will scanf an integer and then will scanf a string, but the contents of the second string overflows the original string
while (exit == 0) {
scanf("%s", input);
if (strcmp(input, "parent") == 0) {
free(input);
ptemp = malloc(sizeof(node_p));
printf("Id: ");
scanf("%d", &ptemp->itemid);
printf("\nElement:");
scanf("%s", ptemp->element);
add_parent_node(parent, ptemp->itemid, ptemp->element);
free(ptemp);
}
}
ptemp is a pointer to a struct containing:
int itemid;
char *element;
I've tried using arrays with predefined size, but nothing seems to work...
Someone that made a comment about nothing overflowing is correct. What you were missing were (in laymans terms) a reservation for characters. Declaring something as char* instead of char[xx] means that you're prepared to reference another part of memory that you're allowed to manipulate with your characters. To keep things simple, I rewritten your code so your program works. Keep in mind that this code relies on users entering strings that are less than 100 to 200 characters long. Feel free to increase the number in square brackets if you need more characters.
I also made an add_parent_node function to verify that the data processing works.
If you want to get a little paranoid and you feel your systems implementation of scanf is screwy, then you can place the following under the while statement:
memset(ptemp,0,sizeof(ptemp));
What that does is floods the entire struct with null characters. This means the value of itemid would be zero since zero is null, and element would be 200 null characters.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int itemid;
char element[200]; //fixed array of chars to actually store a string
}mycollection;
void add_parent_node(char* parentnodename,int itemid,char* element){
printf("Added node as follows\n");
printf("Parent: %s\n",parentnodename);
printf("Item ID: %d\n",itemid);
printf("Element: %s\n\n",element);
}
int main(){
char input[100]; //limit command to 99 characters
mycollection ptemp[1];
while(1){ //while(1) = endless loop
printf("\nEnter command: ");
scanf("%s", input);
if (strcmp(input, "parent") == 0) {
printf("\nId: ");
scanf("%d", &ptemp->itemid);
printf("\nElement:");
scanf("%s", ptemp->element);
add_parent_node("im_the_parent", ptemp->itemid, ptemp->element);
}
if (strcmp(input, "exit") == 0) {
return 0; //return 0 = exit
}
}
}
If you don't want to change anything outside your while loop I think this is what you can do.
while (exit == 0) {
scanf("%s", input);
if (strcmp(input, "parent") == 0) {
if(0 == ptemp ){
/* Allocate memory only once and reuse it.*/
ptemp = malloc(sizeof(node_p));
/* Allocate memory for element. */
ptemp->element = malloc(sizeof(char) * 1024 /* Max string len + 1 */)
}
printf("Id: ");
scanf("%d", &ptemp->itemid);
printf("\nElement:");
scanf("%s", ptemp->element);
add_parent_node(parent, ptemp->itemid, ptemp->element);
}
else if (strcmp(input, "exit") == 0) {
if(0 != ptemp){
/* If memory is allocated for ptemp, free it. */
if(0 != ptemp->element){
free(ptemp->element);
ptemp->element = 0;
}
free(ptemp);
ptemp = 0;
}
free(input);
input = 0;
exit = 1;
break;
}
}

How do I get rid of this new line?

I created a program that asks the user to input their name, and then manipulates it in multiple ways. The final way that it manipulates it is by printing the users name backwards. For instance if the user entered John Doe, the program would print Doe John. The only problem I'm having at this point is stopping my program from putting an unnecessary new line between the last and first name.
Example:
I want Doe John on one line but I get
Doe
John
For my assignment I need to get rid of this extra line. How do I do this?
#include <stdio.h>
#include <string.h>
void removeNewLine (char * userName, int charLenght)
{
int i=0;
do {
if (userName [i]=='\n')
{
userName [i]='\0';
}
i++;
} while (i<charLenght);
}
// This is going to tell me exactly how many real character are in my array
int myCounter (char * userName, int size)
{
int counter=0;
do
{
if(userName [counter]=='\0')
{
return counter; //I always thought that you needed to put your return at the end of the function, this is good to know that you don't need too
}
counter++;
}while (counter<size);
return -1;
}
int main ()
{
printf("Enter your first and last name\n");
char name [250]={'\0'};
char * space;
char *first=NULL, *last = NULL, *firstspace;
char *userName;
int numOfChars=0;
//Prevents the potential problem of an overflow = (sizeof(name)-1)
fgets(name,(sizeof(name)-1),stdin);
//This is what is actually doing the dirty work of removing the extra chars
removeNewLine(userName, numOfChars);
//This is going to count the number of characters that were input by the user
numOfChars = strlen(name)-1;
printf("You Entered: %s \n", name);
printf("There are %zu characters in your name including the space. \n", strlen(name));
char end;
int i;
end = strlen(name) -1;
printf("Your name backwards is");
for (i = end; i >= 0; --i)
{
printf("%c", name [i]);
}
printf("\nLooking for the space in your name \n", name);
firstspace=space=strchr(name, ' ');
*firstspace='\0';
while (space!=NULL)
{
printf("The space was found at character %d\n", space-name+1);
last = space+1;
space=strchr(space+1, ' ');
}
printf("%s%s", last, name);
*firstspace=' ';
//This is just to tell the user how many "real" characters were in there name
printf("\n There are %d actual characters in your name including the space", numOfChars);
}
Do little modification and Interchange these below two lines
removeNewLine(userName, numOfChars);
//This is going to count the number of characters that were input by the user
numOfChars = strlen(name)-1;
Like this
numOfChars = strlen(name); // first find the length of input.
removeNewLine(name, numOfChars); // And now remove newline at the end of input
EDIT
Your CODE
#include <stdio.h>
#include <string.h>
void removeNewLine (char * userName, int charLenght)
{
int i=0;
do {
if (userName [i]=='\n')
{
userName [i]='\0';
}
i++;
} while (i<charLenght);
}
int main ()
{
printf("Enter your first and last name\n");
char name [250]={'\0'};
char * space;
char *first=NULL, *last = NULL, *firstspace;
int numOfChars=0;
//Prevents the potential problem of an overflow = (sizeof(name)-1)
fgets(name,(sizeof(name)-1),stdin);
//This is what is actually doing the dirty work of removing the extra chars
numOfChars = strlen(name); // first find the length of input.
removeNewLine(name, numOfChars); // And now remove newline at the end of input
printf("You Entered: %s \n", name);
printf("There are %zu characters in your name including the space. \n", strlen(name));
char end;
int i;
end = strlen(name) -1;
printf("Your name backwards is");
for (i = end; i >= 0; --i)
{
printf("%c", name [i]);
}
printf("\nLooking for the space in your name \n", name);
firstspace=space=strchr(name, ' ');
*firstspace='\0';
while (space!=NULL)
{
printf("The space was found at character %ld\n", space-name+1);
last = space+1;
space=strchr(space+1, ' ');
}
printf("%s %s", last, name);
*firstspace=' ';
//This is just to tell the user how many "real" characters were in there name
printf("\n There are %d actual characters in your name including the space", numOfChars);
}
Output
Enter your first and last name
John Doe
You Entered: John Doe
There are 8 characters in your name including the space.
Your name backwards iseoD nhoJ
Looking for the space in your name
The space was found at character 5
Doe John
There are 9 actual characters in your name including the space
The best way is to use fgets() with a couple of helper functions:
/*Removes remaining characters from keyboard input buffer until next newline*/
/*Returns 0 if OK, a negative value if EOF.*/
int fpurge(FILE *f)
{
int c;
while((c=fgetc(f))!=EOF && c!='\n')
{ }
return (c==EOF ? -1 : 0);
}
/*Find and remove newline from string*/
/* Returns a nonzero value if found, zero if not. */
int truncate_newline(char *str)
{
int bRet=0;
if(str!=NULL)
{
char *pNewline = strchr(str, '\n');
if(pNewLine!=NULL)
{
bRet = 1;
*pNewLine = '\0';
}
}
return bRet;
}
/*Remove newline from string or excess characters from input buffer,
where appropriate.*/
/* Returns 0 if buffer is full, a positive value if line is complete,
a negative value if EOF (implies buffer full). */
int fclean(char *str, FILE *f)
{
int ret = 1;
if(!truncate_newline(str))
ret = fpurge(f);
return ret;
}
It's used this way:
char buf[42];
fgets(buf, sizeof buf, stdin);
fclean(buf);
Now you have a NULL-terminated, newlineless buf, and nothing in the input buffer to corrupt your next fgets call.
Like to offer an "after accepted" solution.
void *removeNewLineAfter_fgets(char *s) {
if (s) {
size_t l = strlen(s);
if ((l > 0) && (s[l-1] == '\n')) {
s[l-1] = '\0';
}
}
return s;
}
// Usage:
if (removeNewLineAfter_fgets(fgets(name,sizeof(name),stdin)) == NULL) { handle EOF }
BTW: OP does not need -1 in fgets(name,(sizeof(name)-1),stdin).

Resources