I'm trying to write program to ask user to enter First and Last Name. Then my program will result their Full Name (combined First + Last Name) and the length of their Full Name. My Output right now does empty Full Name and 0 length. I guess my problem is at display_name functions. Here is my code so far. Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void display_name(char *fullname);
int count_char( char*x_ptr);
char * get_name(char * first_name, char * last_name);
#define MAX 80 // maximum number of array elements
int main(void)
{
char first_name[MAX];
char last_name[MAX];
char *x_ptr;
system("cls");
printf("Enter Last Name: \n" );
scanf("%s", &last_name );
printf("Enter First Name: \n" );
scanf("%s", &first_name );
x_ptr = get_name(first_name, last_name);
display_name(x_ptr);
puts("");
system("pause");
return 0;
}
char * get_name(char *first_name, char *last_name)
{
static char fullname[MAX];
char x;
x = 0;
strcpy(fullname, first_name);
strcat(fullname, " ");
strcat(fullname, last_name);
while (((fullname[x] = getchar()) != '\n') && (x < (MAX-1)))
{
x++;
}
fullname[x] = '\0';
return(fullname);
}
/* Function to print out string passed to it and display the length of fullname*/
void display_name(char *fullname)
{
char *a;
printf("Your Full name is ");
a = &fullname[0];
while (*a != '\0')
{
putchar(*a);
a++;
}
int length;
length = strlen(fullname);
printf("\nHas %d Characters", length);
length = count_char(fullname);
printf("\nHas %d Non Space Characters", length);
}
/* function to return count of non space characters*/
int count_char( char * x_ptr)
{
char *b;
unsigned int count=0;
b = x_ptr;
while (*b != '\0')
{
if (*b != ' ')
count++;
b++;
}
return
(count);
}
scanf("%s", &last_name );
Compiler complained and you ignored it. It should be scanf("%s", last_name );. Same goes with firstname. Yours had type char (*)[] and scanf expects char* which is what we gave in second case.
This part is doing nothing that you would do to achieve what you are trying to do.
while (((fullname[x] = getchar()) != '\n') && (x < (MAX-1)))
This is using getchar to get the characters from stdin and put it in the char array where you are storing the concatenated name.
Using static char array is not a good solution. The next time you try to use this function - it will overwrite the data previously written by another function. Illustration implementation of the function get_name would be
char * get_name(char *first_name, char *last_name)
{
char *fullname = malloc(strlen(first_name)+2+strlen(last_name));
if(!fullname){
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(fullname, first_name);
strcat(fullname, " ");
strcat(fullname, last_name);
return fullname;
}
Benefit of using this implementation is that - now the data that is being used is not closely coupled with the methods that call this one. So it can be reused independent of it's previous usage in another function.
Also when using the function get_name remember to free the dynamically allocated memory when you are done working with it.
Related
I have written this program that asks the user for a name and then prints the name. Here are the steps in detail:
asks the user for the number of characters the name (i.e. sentence) will have. It includes empty spaces and the terminator character \0, then stores it;
it creates a block of memory with num_char addresses, and stores the address of the first item in ptr;
within the else section, an array of unknown size is declared, which will be used to store the name and its first address is assigned to ptr;
then the array is assigned with size num_char;
Here's the code:
#include <stdio.h>
#include <stdlib.h>
//an attempt at a program that asks for a name, stores it in an array and then prints it
int main() {
int num_char;
char *ptr;
printf("input number of characters of your name (spaces and terminator character included): ");
scanf("%d", &num_char);
ptr = char *malloc(num_char * sizeof(char)); //creates a block of mem to store the input name, with the same size, and then returns the adress of the beginning of the block to ptr
if (ptr == NULL) {
printf("allocation not possible");
} else {
ptr = char name[]; //ptr stores the adress of the first char in string
char name[num_char], //declaration of an array with num_char elements
printf("input name: ");
scanf("%s", name);
printf("input name was: %s", name);
}
return 0;
}
However I get three compilation errors which are:
"expected expression before 'char' " at ptr = char *malloc(num_char * sizeof(char) ); and ptr = char name[];
"expected declaration specifiers or '...' before string constant" at printf("input name: ");
I am a college student just beginning at C and programming in general so a detailed explanation of any error of any kind and how to fix it would be very much appreciated :)
These are syntax errors because:
ptr = char *malloc(num_char * sizeof(char)); should have been ptr = (char *)malloc(num_char * sizeof(char)); or simply ptr = malloc(num_char * sizeof(char));.
ptr = char name[]; is meaningless. You do not need to change ptr at all.
char name[num_char], is a C99 variable length array definition, but with a trailing , so the next line is expected to have another definition, hence the second error.
You must choose to either allocate memory from the heap with malloc() or define an array as a local variable.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int main() {
int num_char;
char *ptr;
printf("input number of characters of your name (spaces and terminator character included): ");
if (scanf("%d", &num_char) != 1 || num_char <= 1) {
printf("invalid input\n");
return 1;
}
/* discard the rest of the input including the newline */
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
//allocate a block of memory to store the name
ptr = malloc(num_char * sizeof(char));
if (ptr == NULL) {
printf("allocation not possible");
} else {
printf("input name: ");
if (scanf("%[^\n]", ptr) == 1)
printf("input name was: %s\n", name);
else
printf("no input was given\n");
free(ptr);
}
return 0;
}
Also note that scanf() may read more than num_char bytes if the input has more non white bytes, so it would be much safer, but non-trivial to given scanf() the information about the array size:
if (ptr != NULL) {
char format[32];
snprintf(format, sizeof format, "%%%d[^\n]", num_char - 1);
printf("input name: ");
if (scanf(format, ptr) == 1) {
printf("input name was: %s\n", name);
// should discard the rest of the line and the newline
} else {
printf("no input was given\n");
}
}
As I stated in the comments, this is a wierd set of requirements for, what I assume is an assignment, here is more or less what you should do, with comments:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void clear_buffer()
{ // routine to clear standard input
int c;
while ((c = getchar()) != '\n' && c != EOF){}
if (c == EOF)
{
exit(EXIT_FAILURE);
}
}
int main()
{
int num_char;
char *ptr;
printf("input number of characters of your name (spaces and terminator character included): ");
// less than 9 + 1 null byte characters for the name not allowed
while (scanf("%d", &num_char) != 1 || num_char < 10)
{
printf("Bad input, try again: ");
clear_buffer();
}
ptr = malloc(num_char); // removed char*, you may wanted a cast,
// but even that is unneeded,
// The size of char is always 1 byte
// I still don't understand why this is asked, but well...
if (ptr == NULL)
{
perror("allocation not possible"); // perror prints the apropriate error
}
else
{
char name[num_char]; // declaration of an array with num_char elements
free(ptr); // to make ptr point to another memory location, it must be freed
ptr = name; // ptr now points to the first element of the name array
clear_buffer();
printf("What's the name ? ");
// read name with spaces from standard input
if (fgets(name, num_char, stdin))
{
name[strcspn(name, "\n")] = '\0'; // remove \n
printf("input name was: %s", ptr); // print name through ptr
}
else
{
puts("Bad input");
}
}
return EXIT_SUCCESS;
}
Pending on ambiguous interpretation...
So I have this simple program in C that I am working on to help me understand structures. There is nothing too complicated about it. However when it gets to the point where it should display the data, it only displays part of the data. The program asks a user for a first and last name, then an amount. Then it should display the first and last name, as well as the amount. It does not display the last name. I am sure this is probably something simple, but I am not sure what I am missing here.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#define NAMESIZE 30
struct data{
float amount;
char firstName[NAMESIZE];
char lastName [NAMESIZE];
}record;
int main()
{
printf("\nEnter the donor's first and last names \n");
printf("Separate names by a space: ");
scanf("%s, %s", record.firstName, record.lastName);
char c;
while ( (c = getchar()) != '\n' && c != EOF )
{
}
// At this point the program does not work correctly
// It will just print the first name not the last name
printf("\nEnter the donation amount: ");
scanf("%f", &record.amount);
// Display the information
printf("\nDonor %s %s gave $%.2f \n", record.firstName, record.lastName, record.amount);
return 0;
}
Any suggestions on this would be greatly appreciated. Thank you
Once I got rid of the extra comma in the first scanf call, it worked. Here is the line that got corrected:
scanf("%s %s", record.firstName, record.lastName);
I had a comma between the two %s, and that was incorrect.
Or maybe can use fgets that have buffer overflow protected and use strtok to split the spacing
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMESIZE 30
struct data{
float amount;
char firstName[NAMESIZE];
char lastName [NAMESIZE];
}record;
int main()
{
char *name = malloc(NAMESIZE);
if (name == NULL) {
printf("No memory\n");
return 1;
}
printf("\nEnter the donor's first and last names \n");
printf("Separate names by a space: ");
//scanf("%s, %s", record.firstName, record.lastName);
fgets(name, NAMESIZE, stdin);
if ((strlen(name) > 0) && (name[strlen (name) - 1] == '\n'))
name[strlen (name) - 1] = '\0';
//split name
int init_size = strlen(name);
char delim[] = " ";
char *ptr = strtok(name, delim);
int idx = 0;
while(ptr != NULL)
{
printf("%d '%s'\n",idx, ptr);
if(idx == 0){
strcpy(record.firstName, ptr);
}
else{
strcpy(record.lastName, ptr);
}
ptr = strtok(NULL, delim);
idx += 1;
}
/*
char c;
while ( (c = getchar()) != '\n' && c != EOF )
{
}
*/
// At this point the program does not work correctly
// It will just print the first name not the last name
printf("\nEnter the donation amount: ");
scanf("%f", &record.amount);
// Display the information
printf("\nDonor %s %s gave $%.2f \n", record.firstName, record.lastName, record.amount);
free(name);
return 0;
}
I need to reverse a given string and display it without using the value At[index] notation , I tried the below program using pointers,but it does not print anything for the reverse string,
Please help!
int main()
{
char* name=malloc(256);
printf("\nEnter string\n");
scanf("%s",name);
printf("\nYou entered%s",name);
int i,count;
count=0;
//find the length
while((*name)!='\0')
{
count++;
name++;
}
//pointer now at
printf("\n%p",name);
printf("\nLength is %d",count);
name=name+count;
//pointer now at
printf("\n%p",name);
for(i=0;i<(count);i++)
{
printf("%c",(*name));
name=name-1;
}
return 0;
}
Remove name=name+count; because of the name++ in the precedent loop moved name pointer to the '\0' char;
#include<stdio.h>
#include<stdlib.h>
int main()
{
char* name=malloc(256);
printf("\nEnter string\n");
scanf("%s",name);
printf("\nYou entered%s",name);
int i,count;
count=0;
//find the length and move name pointer
while((*name)!='\0')
{
count++;
name++;
}
//pointer now at
printf("\nPointer is: %p",name);
printf("\nLength is: %d\n",count);
for(i=1;i<=(count);i++)
{
printf("%c",*(name-i));
}
printf("\n");
return 0;
}
OR change the final loop to
for(i=0;i<(count);i++)
{
name--;
printf("%c",*name);
}
Remove name=name+count; and add name--;
Important: scanf(" %s", name); has no bounds checking on the input. If someone enters more than 255 characters into your program, it may give undefined behaviour.
Now, you have the char array you have the count (number of char in the array), and you make name++ (name has the last char offset) then why do you need to bother doing stuffs like this?
name=name+count;
Try this:
#include <stdio.h>
int main()
{
char* name = malloc(256);
// char name[256];
printf("\nEnter string\n");
// scanf("%s", name);
fgets(name, 254, stdin); // carriage return and null character (256-2)
printf("\nYou entered %s", name);
int i, count;
count = 0;
//find the length
while ((*name) != '\0' && (*name) != '\r') {
count++;
name++;
}
//pointer now at
// printf("\n%p", name);
// printf("\nLength is %d", count);
// name = name + count;
//pointer now at
// printf("\n%p", name);
for (i = count; i >= 0; i--) { // starts from last '\0'
printf("%c", (*name));
name = name - 1;
}
return 0;
}
I got the following output:
Enter string rakeb
You entered rakeb
bekar
The easiest way? Just replace them with their syntactic equivalent:
arr[index] // is sugar for ...
arr + index
Then, instead of using two indices to traverse just use pointers. Using this you can actually find a solution pretty easy:
void nreverse(char * str) {
char * forward = str;
char * backward = str + strlen(str) - 1;
while (forward < backward) {
char temp = *forward;
*forward = *backward;
*backward = temp;
++forward;
--backward;
}
}
Try this which will not only print but also reverse string and store it in name.
#include <stdio.h>
int main()
{
char* name = malloc(256);
char *backup1 = *bakcup2 = name;
printf("\nEnter string\n");
fgets(name, 254, stdin); // carriage return and null character (256-2)
printf("\nYou entered %s", name);
while ((*backup1) != '\0' && (*backup1) != '\r') {
backup1++;
}
backup1--; // Because here backup1 was pointing to '\0' or '\r'.
while(backup1 > backup2){
/* Swapping characters */
char temp;
temp = *backup1;
*backup1 = *backup2;
*backup2 = temp;
backup1--;
backup2++;
}
backup1 = name;
while(*backup1 != '\0' && *backup1 != '\r') {
printf("%c", (*backup1));
backup1++;
}
return 0;
}
Please post code that cleanly compiles
The current posted code is missing the required/used header files
the following code
1) includes error checking
2) limits the length of the user supplied string
to avoid a input buffer overflow
3) eliminates certain lines (commented out)
that caused 'name' to point to the wrong location
4) incorporates '\n' at the end of the printf() format strings
so the info will be printed rather than held
in the buffer for stdout
5) at the end, passes the pointer to the malloc'd memory
to the free() function
6) corrects the loop count when printing the
reverse of the input string
#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME_LEN (256)
int main()
{
char* name=NULL;
char* temp = NULL;
if( NULL ==(name=malloc(256)) )
{ // then malloc failed
perror( "malloc for name[] failed");
exit( EXIT_FAILURE );
}
// implied else, malloc successful
temp = name; // save ptr to malloc'd memory
printf("\nEnter string\n");
if( 1 != scanf("%255s", name) )
{ // then scanf failed
perror( "scanf for name failed");
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("\nYou entered: %s\n",name);
int i,count;
count=0;
//find the length
while((*name)!='\0')
{
count++;
name++;
}
//pointer now at
printf("\nAddress of last char in name[]: %p\n",name);
printf("\nLength is %d\n",count);
//name=name+count;
//pointer now at
//printf("\n%p",name);
for(i=0;i<=count;i++)
{
printf("%c",(*name));
name--;
}
printf( "\n" );
free(temp);
return 0;
} // end function: main
I am trying to build a program that uses dynamic allocation to build an array of strings.
After the user finishes to enter the words he wants into the array i want to print the array one word after the other. I am using pointers to pointers, however it doesn't seem to work:
#define SIZE 256
void paintWords(char **words, int count_words);
void main() {
char **words = NULL;
int flag = 1;
char buffer[SIZE];
int count_words = 0;
char *curr_word;
while (flag)
{
_flushall();
printf("Enter a word:");
gets(buffer);
words = (char**)realloc(words,++count_words*sizeof(char*));
curr_word = (char*)malloc(strlen(buffer) + 1);
words[count_words - 1] = curr_word;
printf("Do you wish to continue(0-no, 1-yes):");
scanf("%d", &flag);
}
paintWords(words, count_words);
}
void paintWords(char **words, int count_words) {
int j = 0;
for (int i = 0; i < count_words; i++)
{
printf("%s\n", words[i][j]);
}
}
Copy buffer to your malloc'ed block with strcpy
strcpy(curr_word, buffer);
you are discarding the read word since you don't put it anywhere
Don't use gets use fgets instead
fgets(buffer, sizeof(buffer), stdin);
this would prevent a buffer overflow.
This is just the jst which in your case is the 0th character of the word
printf("%s\n", words[i][j]);
change it to
printf("%s\n", words[i]);
turn compiler warnings on, it would tell you about printf expecting a char * and recieving char instead.
Also consider the following:
main() should return int.
You don't need to cast malloc.
Don't overwrite your pointer with realloc, use a temporary pointer and assign it to array on success only. Otherwise if realloc returns NULL you will not be able to free(array) for example.
++count_words
words = realloc(words,count_words*sizeof(char*));
words[count_words-1] = malloc(strlen(buffer) + 1);
strcpy(words[count_words-1],buffer);
Later print the array
printf("%s\n",words[i]);
realloc() can fail so
char *temp = realloc(words,count_words*sizeof(char*));
if(temp != NULL)
words = temp;
Few other fixes will be
You shouldn't be using gets which is no more a standard. Use fgets() and note that fgets() comes with a newline character
Check the code below:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 256
void paintWords(char **words, int count_words);
void main() {
char **words = NULL,ch;
int flag = 1;
char buffer[SIZE];
int count_words = 0;
//char *curr_word;
while (flag)
{
printf("Enter a word:");
fgets(buffer,sizeof(buffer),stdin);
words = (char**)realloc(words,++count_words*sizeof(char*));
words[count_words - 1] = (char*)malloc(strlen(buffer) + 1);
strcpy(words[count_words-1],buffer);
printf("Do you wish to continue(0-no, 1-yes):");
scanf("%d", &flag);
while((ch = getchar()) != '\n');
}
paintWords(words, count_words);
}
void paintWords(char **words, int count_words) {
int i;
for (i=0; i < count_words; i++)
{
printf("%s", words[i]);
}
}
I have following code:
int main(){
char sentence[] = "my name is john";
int i=0;
char ch[50];
for (char* word = strtok(sentence," "); word != NULL; word = strtok(NULL, " "))
{
// put word into array
// *ch=word;
ch[i]=word;
printf("%s \n",ch[i]);
i++;
//Above commeted part does not work, how to put word into character array ch
}
return 0;
}
I am getting error: error: invalid conversion from ‘char*’ to ‘char’ [-fpermissive]
I want to store each word into array, can someone help?
To store a whole set of words you need an array of words, or at least an array of pointers pointing to a word each.
The OP's ch is an array of characters and not an array of pointers to characters.
A possible approach would be:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define WORDS_MAX (50)
int main(void)
{
int result = EXIT_SUCCESS;
char sentence[] = "my name is john";
char * ch[WORDS_MAX] = {0}; /* This stores references to 50 words. */
char * word = strtok(sentence, " "); /* Using the while construct,
keeps the program from running
into undefined behaviour (most
probably crashing) in case the
first call to strtok() would
return NULL. */
size_t i = 0;
while ((NULL != word) && (WORDS_MAX > i))
{
ch[i] = strdup(word); /* Creates a copy of the word found and stores
it's address in ch[i]. This copy should
be free()ed if not used any more. */
if (NULL == ch[i])
{
perror("strdup() failed");
result = EXIT_FAILURE;
break;
}
printf("%s\n", ch[i]);
i++;
word = strtok(NULL, " ")
}
return result;
}