reversing a string in c without library function - c

In this program I am trying to take a string as input from the user guessing that the maximum length of the string here is 40 (obviously can exceed).
I'm finding out the length and using the length to create another character array dynamically( only to prevent assigning this array with any random value) and finally, adding the characters from the last to get the reversed string.
It compiles just fine, but upon running, provides no output.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[40];
char *rev;
int i=0;
int l=0;
printf("Enter any statement \n");
scanf("%[^\n]", word);
while(word[i]!='\0')
{
i++;
}
// i contains the length of the string
rev=(char *)malloc(i*sizeof(char));
while(i>0)
{
rev[l]=word[i];
i--;
l++;
}
printf("\n %s", rev);
return 0;
}

You have two (at least) problems: The first one is that you swap characters twice. The second problem is that you also include the terminator character in your swapping.

I believe you have a 'one-off' type error and are not seeing any output because the teminating \0 character is being copied to the first position of rev.

rev[l]=word[i]; should rev[l]=word[i-1];

Point 1:-
In C a string is always ended with '\0'(NULL Termination),you should always manually insert a '\0' at the end,which i think you forgot.But no worries even i did not remember it as well when i started...:) ,Experiences like these will make you from next time.
Point 2:-
Assume you have a string char str[]="ABCD" ;,In memory this would look like this
------------IN Memory----------------
| 'A' || 'B' || 'C' | | 'D' | | '\0' |
-------------------------------------
0 1 2 3 4
Just by looking we can say that its length would be 4 (we know that we don't include '\0' when calculating length). For copying in reverse we need to start with character 'D' whose index is 3,that means you have to start copying from 2nd last character whose index can be can be found from length of string -1.The mistake you did in your above program is you have used length of string (which is 4), to start copying.which copies '\0' as first character in rev[] ,Hence it provides no output.
Other points:-
Based on the above two points i have corrected the mistakes, see comments in the below program to understand it well.And i have used int j;instead of int l; because i felt so confusing.
and please use width specifier when reading strings using scanf(); In your while loop,you should change the condition from i>0 to i>=0 because when i reaches 0,i>0 condition will break the loop before copying the first character from word[] to rev[].
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[40];
char *rev;
int i=0;
int j=0;
printf("Enter any statement \n");
scanf("%39[^\n]", word);//using width specifier,(POINT 1)here 39 because sizeof(word)-1, one left to accommodate '\0' at end.
while(word[i]!='\0')//calculating length of string
{
i++;
}
rev=(char *)malloc(i*sizeof(char)+1);// (POINT 1),here making +1 to accommodate '\0' at end.
i=i-1;//(POINT 2)- Last index of the array is always length of string - 1
while(i>=0)//This should be i>=0 because you also want to copy first character of input string.
{
rev[j]=word[i];
i--;
j++;
}
rev[j]='\0';//(POINT 1) You should end with '\0'.
printf("\n %s", rev);
return 0;
}

Your scanf format string looks weird. Perhaps you are using some strange feature of it that I'm unaware of, so I'll pass on that. But you need to make sure that word is a null terminated string after the user input is done.
while(word[i]!='\0')
This loops counts until it finds the null term. So i will contain the string length: you just invented the strlen() function. It will not contain the string length plus the null terminator length (1).
Therefore
rev=(char *)malloc(i*sizeof(char));
is incorrect, you need to allocate i+1 bytes.
Also, you shouldn't cast the result of malloc, because doing so is completely pointless.
And when you copy, you have to ensure that you also copy the null terminator.

Below code with just one modification should return just correct answer. I changed in 2nd while loop from:
rev[l]=word[i];
to
rev[l]=word[i-1];
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[40];
char *rev;
int i=0;
int l=0;
printf("Enter any statement \n");
scanf("%[^\n]", word);
while(word[i]!='\0')
{
i++;
}
// i contains the length of the string
rev=(char *)malloc(i*sizeof(char));
while(i>0)
{
rev[l]=word[i-1];
i--;
l++;
}
printf("\n %s", rev);
return 0;
}

The code has several memory mistakes and using static memory is also an issue. But for if you are using for practice purpose below are the changes and its explanation.
i--; // you can't place a '\0' to your rev[0] else it would always be NULL string when you print
while(i>=0)
{
rev[l]=word[i];
i--;
l++;
}
rev[l]='\0'; // string should be terminated by '\0'
printf("\n%s\n", rev);

//Reverse of a string without using string functions
#include<stdio.h>
#include<conio.h>
void main()
{
char a[40];
int j=0,len=0;
clrscr();
printf("please enter your name\n");
gets(a); // takes white spaces as characters
printf("the reverse of your name is\n");
while (a[j]!=NULL) // finding the length of the string array
{
len++;
j++;
}
for(int k=len;k>=0;k--)
{
printf("%c",a[k]);
}
getch();
}
Output - please enter your name
dwayne rock johnson
the reverse of your name is
nosnhoj kcor enyawd

As noted, array indices begin at zero and end at length-1. Moreover, if you like, you could rewrite your code in a more cryptic fashion:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[40];
char *rev;
int i=0;
int l=0;
printf("Enter any statement \n");
scanf("%[^\n]", word);
while(word[++i]);
// i contains the length of the string
rev=(char *)malloc(i*sizeof(char));
while(rev[l++]=word[i---1], i>0);
printf("%s\n", rev);
return 0;
}

Related

Appending chars into a String in C with a for loop

I'm still a newbie to C so please forgive me if anything below is wrong. I've searched this up online but nothing really helped.
Right now, I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void appendStr (char *str, char c)
{
for (;*str;str++); // note the terminating semicolon here.
*str++ = c;
*str++ = 0;
}
int main(){
char string[] = "imtryingmybest";
char result[] = "";
for(int i = 0; i < strlen(string); i++){
if(i >= 0 && i <= 3){
appendStr(result, string[i]);
}
}
printf("%s", result);
}
Basically, I'm trying to add the first 4 characters of the String named string to result with a for loop. My code above did not work. I've already tried to use strcat and strncat and neither of them worked for me either. When I used
strcat(result, string[i]);
It returns an error saying that the memory cannot be read.
I know that in this example it might have been easier if I just did
appendStr(result, string[0]);
appendStr(result, string[1]);
appendStr(result, string[2]);
appendStr(result, string[3]);
But there is a reason behind why I'm using a for loop that couldn't be explained in this example.
All in all, I'd appreciate it if someone could explain to me how to append individual characters to a string in a for loop.
The following code doesnt use your methods but successfully appends the first 4 chars to result
#include <stdio.h>
#include <string.h>
int main()
{
// declare and initialize strings
char str[] = "imtryingmybest";
char result[5]; // the 5th slot is for \0 as all strings are null terminated
// append chars to result
strncat(result, str, 4);
// ^ ^ ^
// | | |- number of chars to be appended
// | | - string to be appended from
// | - string to append to
// print string
printf("result: %s\n", result);
return (0);
}
The result of the above is as wanted:
>> gcc -o test test.c
>> ./test
result: imtr
Let me know if anything is not clear so i can elaborate further
string was ruined by the overflow of result buffer.
appendStr can be executed only once. next time strlen(string) will return 0. because *str++ = 0; has been written to the space of string.
result buffer has only 1 byte space, but you write 2 byte to it in appendStr call.
the second byte will ruin string space.
I suggest debug with gdb.
try to get rid of Magic numbers
#define BUFF_SIZE 10 // define some bytes to allocate in result char array
#define COPY_COUNT 4 // count of chars that will be copied
int main(){
char string[] = "imtryingmybest";
char result[BUFF_SIZE] {}; // allocate some chunk of memory
for(size_t i = 0; i < strlen(string); i++){
if(i < COPY_COUNT){
appendStr(result, string[i]);
}
}
printf("%s", result);
}
I showed the solution code Paul Yang showed the problem
As others have pointed out the code has a simple mistake in the allocation of the destination string.
When declaring an array without specifying its size, the compiler deduces it by its initializer, which in your case means a 0 + the NULL character.
char result[] = ""; // means { '\0' };
However, I think that the bigger issue here is that you're effectively coding a Schlemiel.
C strings have the serious drawback that they don't store their length, making functions that have to reach the end of the string linear in time complexity O(n).
You already know this, as shown by your function appendStr()
This isn't a serious issue until start you appending characters or strings in a loop.
In each iteration of your loop appendStr() reaches the last character of the string, and extends the string, making the next iteration a little slower.
In fact its time complexity is O(n²)
Of course this is not noticeable for small strings or loops with few iterations, but it'll become a problem if the data scales.
To avoid this you have to take into account the growing size of the string.
I modified appendStr() to show that now it starts from the last element of result
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void appendStr (char *str, char c, char *orig)
{
printf("i: %ld\n", str - orig);
for (; *str; str++); // note the terminating semicolon here.
*str++ = c;
*str++ = 0;
}
int main()
{
char string[32] = "imtryingmybest";
char result[32] = "";
for(int i = 0; i < strlen(string); i++) {
if(i >= 0 && i <= 3) {
// I'm passing a pointer to the last element of the string
appendStr(&result[i], string[i], result);
}
}
printf("%s", result);
}
You can run it here https://onlinegdb.com/HkogMxbG_
More on Schlemiel the painter
https://www.joelonsoftware.com/2001/12/11/back-to-basics/
https://codepen.io/JoshuaVB/pen/JzRoyp

C - Limit the string length

(Sorry for my bad english !)
I wrote a program that asks you to type a password no longer than a certain number, eight characters in this case. The characters that pass the limit will be cut out from the array:
#include <stdio.h>
#define MAXCHAR 8
main()
{
char password[MAXCHAR];
int i;
char c;
printf("Insert password: MAX 8 CHARS!\n\n");
for(i = 0; i <= MAXCHAR; i++){
c = getchar();
if(i == MAXCHAR){
break;
}
else{
password[i] = c;
}
}
printf("%s\n", password);
}
So the program works BUT there is a "strange" problem. If the limit IS EIGHT and I type a password longer than eight characters
(Example: P455w0rds98)
the output will be like this:
P455w0rd☺
So it puts a smiley at the end and I don't know why. It happens only if a the limit is established at eight.
You must specify the length to print or terminate the string. Otherwise, you will invoke undefined behavior. Try this, in which the latter method is implemented.
#include <stdio.h>
#define MAXCHAR 8
int main(void)
{
char password[MAXCHAR + 1]; /* allocate one more element for terminating null-character */
int i;
char c;
printf("Insert password: MAX 8 CHARS!\n\n");
for(i = 0; i <= MAXCHAR; i++){
c = getchar();
if(i == MAXCHAR){
break;
}
else{
password[i] = c;
}
}
password[MAXCHAR] = '\0'; /* terminate the string */
printf("%s\n", password);
}
Some people say that the if(i == MAXCHAR){ break; } part doesn't look good, so here is another code example:
#include <stdio.h>
#define MAXCHAR 8
int main(void)
{
char password[MAXCHAR + 1]; /* allocate one more element for terminating null-character */
int i;
printf("Insert password: MAX 8 CHARS!\n\n");
/* read exactly 8 characters. To improve, breaking on seeing newline or EOF may be good */
for(i = 0; i < MAXCHAR; i++){
password[i] = getchar();
}
password[MAXCHAR] = '\0'; /* terminate the string */
getchar(); /* to match number of call of getchar() to the original: maybe for consuming newline character after 8-digit password */
printf("%s\n", password);
}
All C-style strings have a terminal \0 character (value 0). This is unique from any other character value, so it can be used to signal the end of the string. The smiley face you observe is just a part of some neighboring memory block that happens to have a null character after the first byte (hence there being only one extra character). The printf function reads bytes from the string given to it, until it sees the \0. To solve your problem, you can either write
password[MAXCHAR] = '\0';
(You will need to reserve one additional byte in your array, for the \0).
Or you can zero-out your array from the get-go:
char password[MAXCHAR + 1] = { };
Or using memset:
memset(password, '\0', sizeof password);
Apart from the answer you already received from MikeCAT, an alternate approach would be to make use of fgets() to read the user input.
In that case , you don't need to keep a count on each character input, you can specify the max size and get done with it. Something like
fgets(password, MAXCHAR, stdin);
can get the job done for you, minus the looping and assignment for each element.
One thing to remember, however, for shorter inputs than the given length, fgets() reads and stores the trailing newline also, you may need to get rid of that manually. Read the linked man page for more ideas.
That said, main() is a very bad and almost non-standard for hosted environments. You should use int main(void), at least to conform to the standards.

I get a an extra and diffrent character when using printf for character array

When I run this program and give laks as input I get laks as output plus one extra character.Also if I want to break the program as soon as a new line is entered i.e when I press enter I want the loop to discontinue but while statement does not seem to work.
# include <stdio.h>
# include <conio.h>
# include <ctype.h>
void main()
{
clrscr();
char person[5];
int i;
printf("enter person name \n");
for(i=0;i<5;i++)
{
scanf("%c",&person[i]);
//while(person[i]!='/n')
}
printf("%s",person);
getch();
}
You are not null terminating your string
So have
person[i] = '\0';
after the for loop.
I would have
char person[6] = "";
and later do a scan
Increase the size of the array by 1 and nul terminate it:
char person[6];
for(i=0;i<5;i++)
{
scanf("%c",&person[i]);
}
person[i] = '\0'; // or person[i] = 0;
If the array is not nul terminated printf will not understand the end of string. The length of a C string is found by searching for the (first) NUL byte.
To make things simpler you could simply do:
char person[6] = { 0 };
for(i=0;i<5;i++)
{
scanf("%c",&person[i]);
}
Also note conio.h is non-standard and the standard mandates main method to return an int.

C String Formatting

I wrote a program that is supposed to solve this this problem. "Write a program that, given a string, a width, and an empty string for output, centers the string in the output area. Use a function that returns 1 if the formatting is successful and 0 if any errors, such as string is greater then length". My problem is that the my program just returns a lot of odd characters when it prints the string out. And it won't flag 0. What can I do to fix my code and or solve the problem better?
FULL CODE:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int formatString(char str[250], char strcopy[250], int width);
int main()
{
char str[250];
char strcopy[250];
int width;
int outcome;
printf("Enter some text:\n");
gets(str);
printf("\nEnter a width (to check): ");
scanf("%d", &width);
printf("What you entered:");
printf("| %s |\n", str);
printf("\n");
outcome = formatString(str, strcopy, width);
if (outcome = 1)
{
printf("String copied.\n");
printf("| %s |", strcopy);
}
else
{
printf("Use a width val. that is the length of string\n");
}
return 0;
}
int formatString(char str[250], char strcopy[250], int width)
{
int sapceCheck;
int temp = 0;
sapceCheck = width - 1;
for (int i = 0; i < width; i++)
{
if (str[i] == '\0')
{
printf("Formating sucessful\n");
strncpy(str, strcopy, sizeof(str)-1); * (str + (sizeof(str) - 1)) = '\0';
temp = 1;
}
}
if (temp == 0)
{
return 0;
}
else
{
printf("Formating not sucessful\n");
printf("Width does not work\n");
return 0;
}
}
Don't miss the answer posted by 'Soravux', which contains all the right advice about how to fix the 'question' code.
Here is an alternate approach. However, the caller must ensure that the destination string 'strcpy' is large enough (length+1) to hold the output:
int formatString(char *str, char *strcopy, int length)
{
size_t strLength;
strLength = strlen(str);
/* Check if the string is greater than the length */
if(strLength > length)
return(0);
/* Print the centered 'str' to 'strcopy'. */
sprintf(strcopy, "%*s%*s",
(length+strLength) / 2, str, //leading spaces & 'str'
length - ((length+strLength) / 2), "" //trailing spaces
);
return(1);
}
A side note on your problem: returning 1 on success and 0 on failure is not the standard function behavior in C literature (aside from functions returning a boolean). Are you following a guide or a course?
You should not arbitrarily pre-allocate 250 chars for your strings. Strings are most often represented by char pointers, handled with dynamic memory allocation. I understand that gets() takes a pre-allocated buffer, but this is a really bad practice. You should consider using the fgets() function and use its maximum number of characters argument for a better security. Hard-coding string length is also hard to maintain (multiple places to modify the length) as well as confusing for readers (it's not clear if the compiler will pass the argument by copy or by reference).
Also, don't try to hide your code. The line containing the strncpy() have two statements, with the unary star pending in-between the two, looking like a multiplication operator. Don't do such things. Put the second statement on a new line.
That being said, you also misunderstood the arguments from the strncpy function: it is destination first, followed by source. You copy an uninitialized buffer (strcopy) into your string. Note that you also misinterpret the value of your temp variable which returns an error when something went well. It also returns 0 instead of 1 as asked.
Last notice: you really should break; your for-loop in your function formatString(), otherwise your strncpy will be executed for every \0 in your string.
I would recommend to check for exercises in a book if you are self-taught or seek the assistance of a TA if you are following a course. They will be able to guide you in the right path for understanding your mistakes.

Strings in C Language

How can you code this in C language if the output is like this? I need strings format of the code because our topic is strings.
#include <stdio.h>
#include <stdlib.h>
void main()
{
char my_string[50];
printf("Enter a word:");
scanf("%s", my_string);
printf("Enter a word:");
scanf("%s", my_string);
// Some unknown code here...
// this part is my only problem to solve this.
getch();
}
Output:
Hello -> (user input)
World -> (user input)
HWeolrllod -> (result)
Okay, you need to do some investigating. We don't, as a general rule, do people's homework for them since:
it's cheating.
you'll probably get caught out if you copy verbatim.
it won't help you in the long run at all.
The C library call for user input that you should use is fgets, along the line of:
char buffer[100];
fgets (buffer, sizeof(buffer), stdin);
This will input a string into the character array called buffer.
If you do that with two different buffers, you'll have the strings in memory.
Then you need to create pointers to them and walk through the two strings outputting alternating characters. Pointers are not an easy subject but the following pseudo-code may help:
set p1 to address of first character in string s1
set p1 to address of first character in string s1
while contents of p1 are not end of string marker:
output contents of p1
add 1 to p1 (move to next character)
if contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
while contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
Translating that into C will take some work but the algorithm is solid. You just need to be aware that a character pointer can be defined with char *p1;, getting the contents of it is done with *p1 and advancing it is p = p + 1; or p1++;.
Short of writing the code for you (which I'm not going to do), there's probably not much else you need.
void main()
{
char my_string1[50],my_string2[50]; int ptr;
ptr=0;
printf("Enter a word : ");
scanf("%s",my_string1);
printf("enter a word");
scanf("%s",my_string2);
while(my_string1[ptr]!='\0' && my_string2[ptr]!='\0')
{
printf("%c%c",my_string1[ptr],my_string2[ptr]);
ptr++;
}
if(my_string1[ptr]!='\0')
{
while(my_string1[ptr]!='\0')
{ printf("%c",my_string1[ptr]);
ptr++;
}
}
else
{
while(my_string2[ptr]!='\0')
{printf("%c",my_string2[ptr]);
ptr++;
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char my_string1[50],my_string2[50];
int i,l1=1,l2=0;
printf("Enter a word:");
scanf("%s", my_string1);
printf("Enter a word:");
scanf("%s", my_string2);
l1=strlen(my_string1); /* Length of 1st string */
l2=strlen(my_string2); /* Length of 2nd string */
if(l1==l2)
{
for(i=0;i<l1;i++)
{
printf("%c%c",my_string1[i],my_string2[i]);
}
}
else
{
printf("Length of the entered strings do not match");
}
}
This is your required code.
You can see that output needs to be a String containing all chars of User String1 and User String2 one by one...
You can do this like...
//add #include<String.h>
int l1=strlen(s1);
int l2=strlen(s2);
if(l1!=l2)
{
printf("length do not match");
return 0;
}
char ansstr[l1+l2];
int i,j=0,k=0;
for(i=0;i<l1+l2;i=i+2)
{
ansstr[i]=s1[j];
ansstr[i+1]=s2[k];
j++;
k++;``
}
//ansstr is your answer
Ok, here's your code. Come on guys, if he asked here it means he can't solve this.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char str1[] = "abcdefghijklmopq";
char str2[] = "jklm";
int len1 = strlen(str1);
int len2 = strlen(str2);
int c1 = 0, c2 = 0;
int max = (len1 > len2) ? len1 : len2 ;
char *result = malloc(len1 + len2);
for(c1 = 0; c1 <= max; c1++) {
if(c1 < len1)
result[c2++] = str1[c1];
if(c1 < len2)
result[c2++] = str2[c1];
}
result[c2] = 0;
printf("\n%s\n", result);
return 0;
}
Basically the loop picks up a character from str1 and appends it to result. Then it picks a character, which stands in the same position as the first from str2 and appends it to result, just as before. I increment c2 by 2 every time because I'm adding 2 chars to result. I check if c1 is bigger that the length of the strings because I want to copy only the characters in the string without the terminating \0. If you know that your strings have the same length you can omit these ifs.

Resources