Newline-terminating input loop not exiting in C - c

I'll preface this with the fact that this is for a homework assignment, so I'm just trying to understand what's going wrong not necessarily exactly how to fix it. I'm working in C, taking a name and grade from the user to create/manipulate structs and use a stack. This while loop won't exit and it isn't reaching the testing print statement at the bottom. line, name, cGrade, and fullData are all character arrays, maxGrade and numGrade are both double variables, s is a stack and item is a void*:
while ((fgets(line, SIZE, stdin)) != NULL && line[0] != '\n') {
if (sscanf(line, "%s %s", name, cGrade) == 2) {
numGrade = atoi(cGrade);
fullData[0] = 0;
if (numGrade >= 0 && numGrade <= 100) {
strcat(fullData, name);
strcat(fullData, " ");
strcat(fullData, cGrade);
printf("Added %s\n", fullData);
item = name;
push(s, item);
if (numGrade > maxGrade) {
maxGrade = numGrade;
}
i++;
} else {
printf("ERROR: Grade must be between 0 and 100\n");
}
}
printf("Outside if: line[0] = %c", line[0]);
}
Edit: adding a screenshot of the output
Screenshot of output
Edit: Adding push code
void push(stack s, void* item){
stackelement* e = malloc(sizeof(stackelement*));
e->contents = malloc(sizeof(void*));
e->next = malloc(sizeof(stackelement*));
e->contents = item;
e->next = s->top;
s->top = e;
}
Here's the struct definition as well. I was given this for the assignment so I'm not allowed to change it.
struck stackelementS {
void* contents;
struct stackelementS* next;
}
typedef struct stackelementS stackelement;
struct stackS {
stackelement* top;
}
typedef struct stackS* stack;

It ended up being the simple fact that using sscanf doesn't include the escape character \0 in the returned string which I assume was messing up some of the string functions. I added a char *end; *end = '\0'; and used strcat() to append it to the name and cGrade. I fixed some of the errors suggested in the comments and it cleaned up the code a lot.
Here's the fixed code:
while(fgets(line, SIZE, stdin) != NULL && line[0] != '\n'){
if(sscanf(line, "%s %s", name, cGrade) == 2){
strcat(name, end);
strcat(cGrade, end);
numGrade = strtod(cGrade, &ptr);
if(numGrade >=0 && numGrade<= 100){
push(s, line);
printf("Added student %s with grade %s to the stack\n", name, cGrade);
if(numGrade > maxGrade){
maxGrade = numGrade;
}
i++;
}
else{
printf("ERROR: Grade must be between 0 and 100, please re-enter the information\n"); }
}
}

Related

How to get whole structure from function?

This is my code:
#include <stdio.h>
typedef struct
{
char name[100];
char number[100];
} contact_t;
void empty_array(char *line)
{
for (int j = 0; line[j] != '\0'; j++)
{
line[j] = '\0';
}
}
void read_text(contact_t *contact)
{
int c, cnt = 0;
int i = 0;
char line[100];
do
{
c = getchar();
if ( (c == '\n') || (c == EOF))
{
if( cnt % 2 == 0)
{
for(int j = 0; line[j] != '\0'; j++)
contact -> name[j] = line[j];
}
else
{
for(int j = 0; line[j] != '\0'; j++)
contact -> number[j] = line[j];
}
empty_array(line);
i = 0;
cnt++;
}
line [i] = c;
i++;
} while (c != EOF);
}
int main()
{
contact_t contact = {"x", "0"};
int *j_ptr;
read_text(&contact);
printf("%s", contact.name);
printf("%s", contact.number);
return 0;
}
I am reading a text file(6 lines, name and number, name and number...) from standard input. Then I assign every second line(starting from the first) from that text file to structure contact.name and the rest are I assign to contact.number. So I have several 3 contact structures. I managed to pass to main only the last one, because I don't know how to get acces to int cnt and again make a for cycle.
This is what last prints give me:
John Green
254454556
UPDATE:
I am sorry for not being clear enough as I was writing this question in a hurry. This code is a part of school project and we are not allowed to work with dynamically allocated memory or use fscanf, fopen, qsort, lsearch, bsearch and hsearch etc. Basically, I would just like to use pointers to index of array line and then in main function use a for cycle again to pass all structures from the function read_text to main function of the program.
A few issues ...
main only provides space for one contact entry
read_text needs to use a dynamic array (vs. overwriting the same entry)
read_text needs to return the list pointer and the count to the caller (e.g. main)
The method used in read_text is a bit convoluted.
Style fixes:
contact -> name --> contact->name
list [i] --> list[i]
Here is the refactored code. It is annotated:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[100];
char number[100];
} contact_t;
int
read_text(contact_t **listp)
{
char buf[1000];
contact_t *list = NULL;
char *cp = NULL;
int cnt = 0;
// loop on input until EOF
while (fgets(buf,sizeof(buf),stdin) != NULL) {
// increase size of list
++cnt;
list = realloc(list,sizeof(*list) * cnt);
// handle error
if (list == NULL) {
perror("realloc/increase");
exit(1);
}
// point to current record
contact_t *contact = &list[cnt - 1];
// get first name
contact->name[0] = 0;
cp = strtok(buf," \n");
if (cp == NULL)
break;
strcat(contact->name,cp);
// add separater
strcat(contact->name," ");
// get last name
cp = strtok(NULL," \n");
if (cp == NULL)
break;
strcat(contact->name,cp);
// get number
cp = strtok(NULL," \n");
if (cp == NULL)
break;
strcpy(contact->number,cp);
}
// trim to actual amount stored (if error)
if ((cp == NULL) && (cnt > 0)) {
--cnt;
list = realloc(list,sizeof(*list) * cnt);
if (list == NULL) {
perror("realloc/trim");
exit(1);
}
}
// give caller the list pointer
*listp = list;
return cnt;
}
int
main(void)
{
int cnt;
contact_t *list;
cnt = read_text(&list);
// print all entries read in
for (int idx = 0; idx < cnt; ++idx) {
contact_t *contact = &list[idx];
printf("'%s' '%s'\n",contact->name,contact->number);
}
return 0;
}
Here is the test input I used:
John Green 254454556
Fred Smith 8765309
Bob Jones 99728967341
Mary Gallagher 4329268757
Here is the program output:
'John Green' '254454556'
'Fred Smith' '8765309'
'Bob Jones' '99728967341'
'Mary Gallagher' '4329268757'
UPDATE:
I am sorry, I should have clarified that I cannot use dynamically allocated memory. Malloc, calloc or also fsangf is not available –
gregalz
Okay, no malloc et. al. Ironically, I was going to use a predefined fixed size array. But, decided to use a dynamic array instead ;-)
Not sure what fsangf is. So, I'll assume that's fscanf. If you're heavily restricted, maybe you should edit your question and post what you can and can not use.
Here's the code that uses just a fixed array:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[100];
char number[100];
} contact_t;
#define NLIST 1000
contact_t list[NLIST];
int
read_text(contact_t *list,int max)
{
char buf[1000];
char *cp = NULL;
int cnt = 0;
// loop on input until EOF
while (fgets(buf,sizeof(buf),stdin) != NULL) {
// don't overflow the max size
if (cnt >= max)
break;
// point to current record and increase list count
contact_t *contact = &list[cnt++];
// get first name
contact->name[0] = 0;
cp = strtok(buf," \n");
if (cp == NULL)
break;
strcat(contact->name,cp);
// add separater
strcat(contact->name," ");
// get last name
cp = strtok(NULL," \n");
if (cp == NULL)
break;
strcat(contact->name,cp);
// get number
cp = strtok(NULL," \n");
if (cp == NULL)
break;
strcpy(contact->number,cp);
}
// trim to actual amount stored (if error)
if ((cp == NULL) && (cnt > 0))
--cnt;
return cnt;
}
int
main(void)
{
int cnt;
cnt = read_text(list,NLIST);
// print all entries read in
for (int idx = 0; idx < cnt; ++idx) {
contact_t *contact = &list[idx];
printf("'%s' '%s'\n",contact->name,contact->number);
}
return 0;
}

malloc() in C returns populated memory

char *string = (char *) malloc(sizeof(char) * sz);
code right before this->void insert_word(word *root, char string1[], int linenumber) { int sz=strlen(string1)<=MAX_WORD_LENGTH?strlen(string1):MAX_WORD_LENGTH; Code block 3 has the entire context
Sometimes malloc() returns a populated memory location while using it.
What bothers me is that this is not random.
(This program consists of taking words from a file and passing them to this function. For THE SAME WORD, the function behaviour(in particular that of malloc()) is different.
For the inputs
string1=0x7fffffffdf10 "lol" root=BST, sz gets a value of 3
The value allocated to string by malloc() is 0x55555555c510 "\340\305UUUU" Why is malloc not pointing to an empty memory location? (This is not random behaviour, it is predictable and repeatable)
Furthermore,this loop runs an infinite amount of time for some reason
while(strcmp(string1,string)!=0)
{
free(string);
string=NULL;
string = (char *) malloc(sizeof(char) * sz);
strncpy(string,string1,sz);
}
MORE RELAVANT CODE
#define MAX_WORD_LENGTH 20
Definition of the structures
typedef struct linkedList
{
int number;
struct linkedList *next;
}list;
typedef struct word_with_count
{
char* string;
list *linenumbers;
struct word_with_count *left;
struct word_with_count *right;
}word;```
[3] ) The function
void insert_word(word *root, char string1[], int linenumber) {
int sz=strlen(string1)<=MAX_WORD_LENGTH?strlen(string1):MAX_WORD_LENGTH;
char *string = (char *) malloc(sizeof(char) * sz);
strncpy(string,string1,sz);
if (root==NULL) {
return;
} else if (strcmp(string, root->string) < 0) {
if (root->left == NULL) {
root->left = createword(string, linenumber);
} else {
insert_word(root->left, string, linenumber);
}
} else if (strcmp(string, root->string) > 0) {
if (root->right == NULL) {
root->right = createword(string, linenumber);
} else {
insert_word(root->right, string, linenumber);
}
} else {
append_list(linenumber, root->linenumbers);
}
free(string);
}
main() which calls this function
int main() {
char path[MAX_PATH_LENGTH];
FILE *fp;
fgets(path, MAX_PATH_LENGTH, stdin);
if (strlen(path) > 0 && path[strlen(path) - 1] == '\n')
path[strlen(path) - 1] = '\0';
fp = fopen(path, "r");
if (fp == NULL) {
printf("File not found\n");
return 0;
}
char ch;
int line_count = 1;
char current_word[MAX_WORD_LENGTH] = "";
word *root = NULL;
while (!feof(fp)) {
ch = fgetc(fp);
//printf("%c", ch);
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') {
if (ch >= 'A' && ch <= 'Z')
ch = ch - 'A' + 'a';
strncat(current_word, &ch, 1);
} else if (ch == '-') {
continue;
} else {
if (strlen(current_word) > 2) {
if (root == NULL) {
root = createword(current_word, line_count);
} else {
insert_word(root, current_word, line_count);
}
}
memset(current_word, 0, sizeof(current_word));
if (ch == '\n') {
line_count++;
}
}
}
if (strlen(current_word) > 2) {
if (root == NULL) {
root = createword(current_word, line_count);
} else {
insert_word(root, current_word, line_count);
}
}
fclose(fp);
// print_tree(root);
//printf("\n");
//print_tree(root);
int status=delete_low_ocurrence(root, NULL, 3);
if (status == -1)root = NULL;
print_tree(root);
freetree(root);
return 0;
}
5)Auxilary function used by this function
word* createword(char string[], int linenumber)
{
word *newword = (word*)malloc(sizeof(word));
int sz=strlen(string)<=MAX_WORD_LENGTH?strlen(string):MAX_WORD_LENGTH;
newword->string = (char*)malloc(sizeof(char)*sz);
strncpy(newword->string, string,sz);
newword->linenumbers = (list*)malloc(sizeof(list));
newword->linenumbers->number = linenumber;
newword->linenumbers->next = NULL;
newword->left = NULL;
newword->right = NULL;
return newword;
}
Textfile given as input
much2f
much3f
lol
lol
lol
qwertyuiopasdfghjklzxcvbnmqwertyuiop
qwertyuiopasdfghjklzxcvbnmqwertyuiop
qwertyuiopasdfghjklzxcvbnmqwertyuiop
qwertyuiopasdfghjklzxcvbnmqwertyuiop
Why is malloc not pointing to an empty memory location?
Because it can. The content of the allocated memory via malloc() is not specified.
If code needs zeroed out memory, see calloc().
Bad code
strncpy(string,string1,sz) does not result in string being a string as it may lack null character termination. The following (strcmp(string... is then undefined behavior. Instead, do not use strncpy(), use strcpy() and make certain the prior allocation has enough room for the terminating null character.
strncpy(string,string1,sz);
...
} else if (strcmp(string, root->string) < 0) { // bad
Repaired code
word* createword(const char string[], int linenumber) {
word *newword = calloc(1, sizeof *newword);
size_t length = strlen(string);
if (length > MAX_WORD_LENGTH) {
length = MAX_WORD_LENGTH;
}
char *s = malloc(length + 1); // Include room for the \0
list *linenumbers = calloc(1, sizeof *linenumbers);
// Test allocation success
if (newword == NULL || s == NULL || linenumbers == NULL) {
free(newword);
free(s);
free(linenumbers);
return NULL;
}
memcpy(s, string, length); // Only copy the first 'length' characters.
s[length] = 0;
newword->string = s;
newword->linenumbers = linenumbers;
newword->linenumbers->number = linenumber;
newword->linenumbers->next = NULL;
newword->left = NULL;
newword->right = NULL;
return newword;
}
Why is “while ( !feof (file) )” always wrong?
feof(fp) improperly used here. fgetc() returns 257 different values. Do not use char ch.
//char ch;
//...
//while (!feof(fp)) {
// ch = fgetc(fp);
int ch;
...
while ((ch = fgetc(fp)) != EOF) {;
This is quite normal behaviour. 'malloc' just does the memory allocation, it makes no commitment on what's already in that memory location. What you probably need is 'calloc', which clears the memory and then allocates it to your program.

Why can't i loop through this stack?

I'm trying to make a parentheses checker with implementing stack. The program will print valid if the input have a correct parentheses pattern
input: {[()]}
output: valid
input: {()[()]}
output: valid
input: (()))
output: unvalid
continuously
But what happen after i input the data is :
()
the program prints this unlimited loop
valid
valid
valid
valid
valid
. . . and so on
same with
(()))
It works normally if put break; on here, but it won't be continuous and would instantly ends the program, and wont ask for the input again.
if(isempty(stack)){
printf("Valid parenthesis expression\n");
break;
} else{
printf("Invalid parenthesis expression\n");
break;
}
I can't seem to find the reason why this happened,
can anyone help me or give me some advice about what's going on? So that I can loop to ask for input and print the valid/invalid just only one time?
#include<stdio.h>
#include<malloc.h>
#include<string.h>
typedef struct data{
char parent;
struct data *next;
}DATA;
void push(DATA **stack, char parentheses);
int isempty(DATA *stack);
void pop(DATA **stack);
int top(DATA *stack);
int main(int argc, char const *argv[]){
DATA *stack;
char parentheses[100];
int i, flag = 1;
do{
//PUSH
stack = NULL;
printf("Enter parentheses: ");
scanf("%[^\n]", &parentheses);
if(strcmp(parentheses, "-1") == 0){
break;
}
for(i = 0; i < strlen(parentheses); i++){
if(parentheses[i] == '{' || parentheses[i] == '[' || parentheses[i] == '('){
push(&stack, parentheses[i]);
} else if (stack == NULL){
printf("Invalid parenthesis expression\n");
break;
} else if(parentheses[i] == '}' && top(stack) == '{'){
pop(&stack);
} else if (parentheses[i] == ']' && top(stack) == '['){
pop(&stack);
} else if (parentheses[i] == ')' && top(stack) == '('){
pop(&stack);
} else if(parentheses[i] != '{' || parentheses[i] != '[' || parentheses[i] != '(' || parentheses[i] != '}' || parentheses[i] != ']' || parentheses[i] != ']') {
printf("Invalid parenthesis expression\n");
break;
}
}
//POP
if(isempty(stack)){
printf("Valid parenthesis expression\n");
} else{
printf("Invalid parenthesis expression\n");
}
}while(1);
return 0;
}
void push(DATA **stack, char parentheses){
DATA *node = (DATA*) malloc(sizeof(DATA));
node -> parent = parentheses;
node -> next = NULL;
if(!isempty(*stack)) node->next = *stack;
*stack = node;
}
int isempty(DATA *stack){
if(stack == NULL) return 1;
else return 0;
}
void pop(DATA **stack){
DATA *temp = *stack;
*stack = (*stack)->next;
free(temp);
}
int top(DATA *stack){
return stack -> parent; //STACK !ISEMPTY
}
scanf("%[^\n]", &parentheses);
must be
scanf(" %[^\n]", parentheses);
notice the space before the '%' to bypass the newline coming from a previous input, without it on the second turn scanf does nothing. To detect that case and also any invalid input I encourage you to always check the value scanf returns.
In case the input has at least 100 characters you write out of parentheses, do
if (scanf(" %99[^\n]", parentheses) != 1) {
/* EOF */
return -1;
}
parentheses is an array, if you want to use "&" it is specifying the index 0 so &parentheses[0]
Note flag is unused
When you detect an invalid case you can indicate "Valid parenthesis expression" :
pi#raspberrypi:/tmp $ ./a.out
Enter parentheses: (
Invalid parenthesis expression
Enter parentheses: )
Invalid parenthesis expression
Valid parenthesis expression
When the stack is not empty after the for you do not free the still present allocated elements, you have memory leaks.
Because you just save characters in the stack it is much more simple and cheaper in memory to just use an array of char. Because the input is limited to 99 (without the final null character) the stack needs to save 99 characters too, and in fact parentheses can be used for the stack
A proposal still using your stack, fixing problems and also reducing the number tests and simplifying stack functions :
#include<stdio.h>
#include<malloc.h>
#include<string.h>
typedef struct data{
char parent;
struct data *next;
} DATA;
void push(DATA **stack, char parentheses);
int isempty(DATA *stack);
void pop(DATA **stack);
int top(DATA *stack);
int main(int argc, char const *argv[]){
DATA *stack = NULL;
char parentheses[100];
char * p;
while (fputs("Enter parentheses: ", stdout),
(scanf(" %99[^\n]", parentheses) == 1) && strcmp(parentheses, "-1")) {
for (p = parentheses; *p; ++p) {
if ((*p == '{') || (*p == '[') || (*p == '('))
push(&stack, *p);
else {
char o;
if (*p == '}')
o = '{';
else if (*p == ')')
o = '(';
else if (*p == ']')
o = '[';
else
o = 0;
if (isempty(stack) || (top(stack) != o))
break;
pop(&stack);
}
}
if (!isempty(stack) || *p) {
puts("Invalid parenthesis expression");
while (! isempty(stack))
pop(&stack);
}
else if (!*p)
puts("Valid parenthesis expression");
}
return 0;
}
void push(DATA **stack, char parentheses) {
DATA *node = malloc(sizeof(DATA));
node->parent = parentheses;
node->next = *stack;
*stack = node;
}
int isempty(DATA *stack) {
return (stack == NULL);
}
void pop(DATA **stack) {
DATA *temp = *stack;
*stack = (*stack)->next;
free(temp);
}
int top(DATA *stack) {
return stack->parent;
}
Compilation and execution:
pi#raspberrypi:/tmp $ gcc -g -Wall s.c
pi#raspberrypi:/tmp $ ./a.out
Enter parentheses: ({[]}())
Valid parenthesis expression
Enter parentheses: (
Invalid parenthesis expression
Enter parentheses: )
Invalid parenthesis expression
Enter parentheses: (]
Invalid parenthesis expression
Enter parentheses: -1
pi#raspberrypi:/tmp $

Printing top 10 recurring words in a file

Edited question:
Hi guys, my goal is to print the top 10 occurring words in a file, I have managed to get everything to work from reading the file to counting word occurrences and printing it, but when I implement my qsort I get a segfault. I looked over my pointers and they look okay to me, I would appreciate any feedback.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 51
struct words
{
char *ch;
int index;
struct words *pNext;
};
struct words* createWordCounter(char *ch)
{
struct words *pCounter = NULL;
pCounter = (struct words*)malloc(sizeof(char));
pCounter->ch = (char*)malloc(strlen(ch)+1);
strcpy(pCounter->ch, ch);
pCounter->index = 1;
pCounter->pNext = NULL;
return pCounter;
}
struct words *pStart = NULL;
char* removePunc(struct words* ch)
{
char *src = ch, *dst = ch;
while (*src)
{
if (ispunct((unsigned char)*src))
{
src++;
}
else if (isupper((unsigned char)*src))
{
*dst++ = tolower((unsigned char)*src);
src++;
}
else if (src == dst)
{
src++;
dst++;
}
else
{
*dst++ = *src++;
}
}
*dst = 0;
}
void addWord(char *word)
{
struct words *pCounter = NULL;
struct words *pLast = NULL;
if(pStart == NULL)
{
pStart = createWordCounter(word);
return;
}
pCounter = pStart;
while(pCounter != NULL)
{
if(strcmp(word, pCounter->ch) == 0)
{
++pCounter->index;
return;
}
pLast = pCounter;
pCounter = pCounter->pNext;
}
pLast->pNext = createWordCounter(word);
}
void printWord(struct words *pCounter)
{
printf("\n%-30s %5d\n", pCounter->ch, pCounter->index);
}
//sort
int compare (const void * a, const void * b){
struct words *A1 = (struct words *)a;
struct words *B1 = (struct words *)b;
return B1->index - A1->index;
/*
if ((A1->count - B1->count) > 0)
return -1;
else if ((A1->count - B2->count) < 0)
return 1;
else
return 0;
*/
}
int main(int argc, char * argv[])
{
struct words *pCounter = NULL;
char temp[MAX];
FILE *fpt;
if(argc == 2)
{
printf("File name is: %s\n",argv[1]);
fpt = fopen(argv[1], "r");
//fail test
if(fpt == NULL)
{
printf("cannot open file, exiting program...\n");
exit(0);
}
//get the data out of the file and insert in struct
int wordCounter = 0;
int i = 0;
int lines = 0;
while((fscanf(fpt, "%s ", &temp)) == 1)
{
removePunc(temp);
addWord(temp);
if(temp == ' ')
i++;
if(temp == '\n')
lines++;
wordCounter++;
}
/*
pCounter = pStart;
while(pCounter != NULL)
{
printWord(pCounter);
pCounter = pCounter->pNext;
}
*/
//sort
qsort(pCounter, wordCounter, sizeof(struct words), compare);
for(int j = 0; i < 10; i++)
{
printWord(pCounter);
}
}
fclose(fpt);
return 0;
}
First temp is already a pointer, so do not include '&' before it in fscanf. Second, don't skimp on buffer size (e.g. #define MAX 1024). Third, protect your array bounds with the field-width modifier and don't put trailing whitespace in your format-string.
Putting it altogether (presuming you use 1024 as MAX, you can use
fscanf(fpt, "1023%s", temp))
Well done on checking the return of fscanf during your read.
Adding to the things that have already been mentioned.
In createWordCounter(...)
pCounter = (struct words*)malloc(sizeof(char));
you are allocating memory for a char. Even though the pointer to a struct is the pointer to its first member, the first element of words is a pointer to a char. It is better to be careful and write
struct words *pCounter = malloc(sizeof *pCounter);
Also, be mindful of operator precedence.
In addWord(...) you have
++pCounter->index;
What that does is increment the pointer pCounter before accessing index. If you are trying to increment index, it should be
++(pCounter->index);
or
pCounter->index++;
I recommend striping your program down to its bare essentials and test each part one at a time systematically to narrow down the cause of your errors.
I think the main problem is the size of temp array when you try to using fscanf.
while((fscanf(fpt, "%s ", temp)) == 1)
When the length of one line is bigger than MAX, segmentation fault occur.
You can change your code like this
#define SCANF_LEN2(x) #x
#define SCANF_LEN(x) SCANF_LEN2(x)
//...
//your original code
//...
while((fscanf(fpt, "%"SCANF_LEN(MAX)"s ", temp)) == 1)
By the way, you should check
(1) compile warning about type
char* removePunc(struct words* ch)
should be char* removePunc(char *ch)
if(temp == ' ') should be if(temp[0] == ' ')
if(temp == '\n') should be if(temp[0] == '\n')
(2) malloc size
pCounter = (struct words*)malloc(sizeof(char)); should be pCounter = (struct words*)malloc(sizeof(struct words));
(3) remember free after using malloc

Program to reverse a string in C without declaring a char[]

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

Resources