Reversing a string without using any libraries - arrays

Now I want to implement a function to "reverse" a given string. My idea was not to swap, rather I thought of declaring a new array in the implemented function to absorb the new string in its reversed state.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
void reverseString( char string[ ], int size );
int main()
{
char string[ 14 ] = "reverse me";
printf( "The string is: %s\n", string );
reverseString( string, 14 );
return 0;
}
void reverseString( char string[ ], int size )
{
int i, j;
char newString[ size ];
for( ( i = ( size ) ) & ( j = 0 ); ( i >= 0 ) && ( j < ( size ) ); i-- & j ++ )
{
newString[ j ] = string[ i ];
}
printf( "\nThe string reversed: %s\n", newString );
}
could anybody please help me to get the idea of reversing strings? Was I approaching the idea when looking at my code or what ?!

function reverseString(string) {
var splitedString = string.split("");
var reverseArray = splitedString.reverse();
var joinArray = reverseArray.join("");
return joinArray;
}
var newString = reverseString("hello");
console.log(newString);
Are you expecting something like this?

A String can be referred to as an array of characters with a null character '\0' at the end of it. If a string is "Banana", then actually the compiler treats it as "Banana\0". When dealing with strings in the program, you have to remember to append the null character to the string that you create.
Here is the working code for the same -
#include <stdio.h>
int main()
{
char string[10] = "banana";
char reverse[10];
int start, end, length = 0;
// Calculating string length - to be used when length is not already known
/*while (string[length] != '\0')
length++;*/
//in this case
length=10;
end = length - 1; /*this is done because indexing in arrays and strings starts
at 0, not at 1...so string[0] gives first character of the
string and string[size-1] gives the last character of the
string*/
for (start = 0; start < length; start++)
{
reverse[start] = string[end];
end--;
}
reverse[start] = '\0'; //here we add the null character to the end of the string
printf("%s\n", reverse);
return 0;
}
Looking at your code, your idea was correct. You just need to brush up some concepts like String indexing, Null character in strings etc.
The same thing can be done using library functions as well.

Related

Replacing words in a string with words given in a 2D array

I'm currently working on a program that corrects given words in a sentence to be more polite.
I'm building a function that is given the original sentence and a 2D array, that stores the words we should look for and the ones we will replace them with.
This is my main function where the "dictionary" is declared:
int main(){
const char * d1 [][2] =
{
{ "hey", "hello" },
{ "bro", "sir" },
{ NULL, NULL }
};
printf("%s\n", newSpeak("well hey bro", d1) );
}
This functions job is to go through every pointer of the original string and check it with the first character of each word, that could potentially be 'bad'. If it catches the first letter, then it will go through the rest of the word and if it goes all the way to the end of the word, it will skip the original word and replace it with the 'good' word.
This is the function itself:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
char * newSpeak ( const char * text, const char * (*replace)[2] )
{
char * result = (char*)malloc( sizeof(char) );
int resIndex = 0; // Pointer to final text
int matches = 0; // 1 - Matches word from library, 0 - Does not
// Run through the whole original text
for ( int index = 0; text[index] != '\0'; index++ ){
for ( int line = 0; replace[line][0] != NULL; line++ ){
// If the first letter of the word matches, do the others match too?
// If yes, don't rewrite the original word, skip it, and write the replacement one by one.
if ( replace[line][0][0] == text[index] ){
matches = 1;
// Check one by one if letters from the word align with letters in the original string
for ( int letter = 0; replace[line][0][letter] != '\0'; letter++ ){
if ( replace[line][0][letter] != text[index + letter] ){
matches = 0;
break;
}
}
// If the whole word matches, skip what would be copied from original text (the bad word) and put in replacement letter by letter
if ( matches == 1 ){
// Push pointer of original string after the word
index += strlen( replace[line][0] );
for ( int r = 0; r < strlen( replace[line][1] ); r++){
result = (char*)realloc(result, (strlen( result ) + 1) * sizeof(char));
result[resIndex + r] = replace[line][1][r];
index += r;
}
}
}
}
if ( matches == 0 ){
result = (char*)realloc(result, (strlen( result ) + 1) * sizeof(char));
result[resIndex] = text[index];
}
resIndex++;
}
return result;
}
After this is run, my expected outcome is well hello sir, but instead, the function only returns well hello.
I am looking for an explanation to why the loop would stop and not check for the rest of the string, any help would be appreciated.
At least this problem:
strlen( result ) in result = (char*)realloc(result, (strlen( result ) + 1) * sizeof(char)); is not valid as result does not point to a string. Missing null character.

Convert String into Array of Strings in C

I'm trying to divide a string of alphabetically sorted words char *str = "a/apple/arm/basket/bread/car/camp/element/..."
into an array of strings alphabetically like so:
arr[0] = "a/apple/arm"
arr[1] = "basket/bread"
arr[2] = "car/camp"
arr[3] = ""
arr[4] = "element"
...
I'm not very skilled in C, so my approach was going to be to declare:
char arr[26][100];
char curr_letter = "a";
and then iterate over each char in the string looking for "/" follow by char != curr_letter, then strcpy that substring to the correct location.
I'm not sure if my approach is very good, let alone how to implement it properly.
Any help would be greatly appreciated!
So we basically loop through the string, and check if we found the "split character' and we also check that we didn't find the 'curr_letter' as the next character.
We keep track of the consumed length, the current length (used for memcpy later to copy the current string to the array).
When we find a position where we can add the current string to the array, we allocate space and copy the string to it as the next element in the array. We also add the current_length to consumed, and the current_length is reset.
We use due_to_end to find out if we have a / in the current string, and remove it accordingly.
Try:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *str = "a/apple/arm/basket/bread/car/camp/element/...";
char split_char = '/';
char nosplit_char = 'a';
char **array = NULL;
int num_elts = 0;
// read all the characters one by one, and add to array if
// your condition is met, or if the string ends
int current_length = 0; // holds the current length of the element to be added
int consumed = 0; // holds how much we already added to the array
for (int i = 0; i < strlen(str); i++) { // loop through string
current_length++; // increment first
int due_to_end = 0;
if ( ( str[i] == split_char // check if split character found
&& ( i != (strlen(str) - 1) // check if its not the end of the string, so when we check for the next character, we don't overflow
&& str[i + 1] != nosplit_char ) ) // check if the next char is not the curr_letter(nosplit_char)
|| (i == strlen(str) - 1 && (due_to_end = 1))) { // **OR**, check if end of string
array = realloc(array, (num_elts + 1) * sizeof(char *)); // allocate space in the array
array[num_elts] = calloc(current_length + 1, sizeof(char)); // allocate space for the string
memcpy(array[num_elts++], str + consumed, (due_to_end == 0 ? current_length - 1 : current_length)); // copy the string to the current array offset's allocated memory, and remove 1 character (slash) if this is not the end of the string
consumed += current_length; // add what we consumed right now
current_length = 0; // reset current_length
}
}
for (int i = 0; i < num_elts; i++) { // loop through all the elements for overview
printf("%s\n", array[i]);
free(array[i]);
}
free(array);
}
Yes, the approach that you specify in your question seems good, in principle. However, I see the following problem:
Using strcpy will require a null-terminated source string. This means if you want to use strcpy, you will have to overwrite the / with a null character. If you don't want to have to modify the source string by writing null characters into it, then an alternative would be to use the function memcpy instead of strcpy. That way, you can specify the exact number of characters to copy and you don't require the source string to have a null terminating character. However, this also means that you will somehow have to count the number of characters to copy.
On the other hand, instead of using strcpy or memcpy, you could simply copy one character at a time from str into arr[0], until you encounter the next letter, and then copy one character at a time from str into arr[1], and so on. That solution may be simpler.
In accordance with the community guidelines for homework questions, I will not provide a full solution to your problem at this time.
EDIT: Since another answer has already provides a full solution which uses memcpy, I will now also provide a full solution, which uses the simpler solution mentioned above of copying one character at a time:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define NUM_LETTERS 26
#define MAX_CHARS_PER_LETTER 99
int main( void )
{
//declare the input string
char *str =
"a/apple/arm/basket/bread/car/camp/element/"
"frog/glass/saddle/ship/water";
//declare array which holds all the data
//we must add 1 for the terminating null character
char arr[NUM_LETTERS][MAX_CHARS_PER_LETTER+1];
//this variable will store the current letter that we
//have reached
char curr_letter = 'a';
//this variable will store the number of chars that are
//already used in the current letter, which will be a
//number between 0 and MAX_CHARS_PER_LETTER
int chars_used = 0;
//this variable stores whether the next character is
//the start of a new word
bool new_word = true;
//initialize the arrays to contain empty strings
for ( int i = 0; i < NUM_LETTERS; i++ )
arr[i][0] = '\0';
//read one character at a time
for ( const char *p = str; *p != '\0'; p++ )
{
//determine whether we have reached the end of a word
if ( *p == '/' )
{
new_word = true;
}
else
{
//determine whether we have reached a new letter
if ( new_word && *p != curr_letter )
{
//write terminating null character to string of
//previous letter, overwriting the "/"
if ( chars_used != 0 )
arr[curr_letter-'a'][chars_used-1] = '\0';
curr_letter = *p;
chars_used = 0;
}
new_word = false;
}
//verify that buffer is large enough
if ( chars_used == MAX_CHARS_PER_LETTER )
{
fprintf( stderr, "buffer overflow!\n" );
exit( EXIT_FAILURE );
}
//copy the character
arr[curr_letter-'a'][chars_used++] = *p;
}
//the following code assumes that the string pointed to
//by "str" will not end with a "/"
//write terminating null character to string
arr[curr_letter-'a'][chars_used] = '\0';
//print the result
for ( int i = 0; i < NUM_LETTERS; i++ )
printf( "%c: %s\n", 'a' + i, arr[i] );
}
This program has the following output:
a: a/apple/arm
b: basket/bread
c: car/camp
d:
e: element
f: frog
g: glass
h:
i:
j:
k:
l:
m:
n:
o:
p:
q:
r:
s: saddle/ship
t:
u:
v:
w: water
x:
y:
z:
Here is another solution which uses strtok:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_LETTERS 26
#define MAX_CHARS_PER_LETTER 99
int main( void )
{
//declare the input string
char str[] =
"a/apple/arm/basket/bread/car/camp/element/"
"frog/glass/saddle/ship/water";
//declare array which holds all the data
//we must add 1 for the terminating null character
char arr[NUM_LETTERS][MAX_CHARS_PER_LETTER+1];
//this variable will store the current letter that we
//have reached
char curr_letter = 'a';
//this variable will store the number of chars that are
//already used in the current letter, which will be a
//number between 0 and MAX_CHARS_PER_LETTER
int chars_used = 0;
//initialize the arrays to contain empty strings
for ( int i = 0; i < NUM_LETTERS; i++ )
arr[i][0] = '\0';
//find first token
char *p = strtok( str, "/" );
//read one token at a time
while ( p != NULL )
{
int len;
//determine whether we have reached a new letter
if ( p[0] != curr_letter )
{
curr_letter = p[0];
chars_used = 0;
}
//count length of string
len = strlen( p );
//verify that buffer is large enough to copy string
if ( chars_used + len >= MAX_CHARS_PER_LETTER )
{
fprintf( stderr, "buffer overflow!\n" );
exit( EXIT_FAILURE );
}
//add "/" if necessary
if ( chars_used != 0 )
{
arr[curr_letter-'a'][chars_used++] = '/';
arr[curr_letter-'a'][chars_used] = '\0';
}
//copy the word
strcpy( arr[curr_letter-'a']+chars_used, p );
//update number of characters used in buffer
chars_used += len;
//find next token
p = strtok( NULL, "/" );
}
//print the result
for ( int i = 0; i < NUM_LETTERS; i++ )
printf( "%c: %s\n", 'a' + i, arr[i] );
}

How to get the length of this array without strlen(), sizeof(arr) / sizeof(arr[0]); does not work, C language

This program, tokenizes a user input string, removes extra spaces and saves each word into a 2D array and then print the tokens
EXAMPLE:
input: " Hello world string house and car"
output and EXPECTED output:
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
THE PROBLEM:
the problem is that I achieved this by using strlen() function when printing the tokens(code located at the very bottom), I am not supposed to use any other library than stdio.h and stdlib.h, since strlen() function is defined in string.h i tried to use sizeof(arr) / sizeof(arr[0]); but it does not work as I want, the result using sizeof is :
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
�oken[6]: ��
token[7]: �
token[8]: ����
token[9]: �
token[10]:
I WOULD LIKE TO HAVE THE EXPECTED OUTPUT WITHOUT USING STRLEN()
#include<stdio.h>
#include <stdlib.h>
#define TRUE 1
char tokenize(char *str, char array[10][20])
{
int n = 0, i, j = 0;
for(i = 0; TRUE; i++)//infinite loop until is the end of the string '\0'
{
if(str[i] != ' '){
//position 1, char 1
array[n][j++] = str[i];// if, it is not space, we save the character
}
else{
array[n][j++] = '\0';//end of the first word
n++;// position for next new word
j=0;// start writting char at position 0
}
if(str[i] == '\0')
break;
}
return 0;
}
//removes extra spaces
char* find_word_start(char* str){
/*also removes all extra spaces*/
char *result = (char*) malloc(sizeof(char) *1000);
int c = 0, d = 0;
// no space at beginning
while(str[c] ==' ') {
c++;
}
while(str[c] != '\0'){ // till end of sentence
result[d++] = str[c++]; //take non-space characters
if(str[c]==' ') { // take one space between words
result[d++] = str[c++];
}
while(str[c]==' ') { //
c++;
}
}
result[d-1] = '\0';
//print or return char?
return result;
free(result);
}
int main()
{
char str[]=" Hello world string dudes and dudas ";
//words, and chars in each word
char arr[10][20];
//call the method to tokenize the string
tokenize(find_word_start(str),arr);
int row = sizeof(arr) / sizeof(arr[0]);
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
for(int i = 0;i <= strlen(arr);i++)
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
printf("token[%d]: %s\n", i, arr[i]);
return 0;
}
Your code using strlen() may appear the work in this instance but it is not correct.
strlen(arr) makes no semantic sense because arr is not a string. It happens in this case to return 5 because arr has the same address as arr[0], then you kludged it to work for the 6 word output by using the test i <= strlen(arr) in the for loop. The two values strlen(arr) and the number of strings stored in arr are not related.
The expression sizeof(arr) / sizeof(arr[0]) determines the run-time constant number arrays within the array of arrays arr (i.e. 10), not the number of valid strings assigned. It is your code's responsibility to keep track of that either with a sentinel value such as an empty string, or by maintaining a count of strings assigned.
I suggest you change tokenize to return the number of strings (currently it is inexplicably defined to return a char, but in fact only ever rather uselessly returns zero):
int tokenize( char* str, char array[][20] )
{
...
return n ;
}
Then:
int rows = tokenize( find_word_start(str), arr ) ;
for( int i = 0; i < rows; i++ )
{
printf( "token[%d]: %s\n", i, arr[i] ) ;
}

I need help understanding the code for reversing a string

I need help understanding a function for reversing the array of string.
I have been looking through a few codes, and just trying to understand it. It is a function using a pointer.
void ReverseString(char *pStr){
int length = 0;
int i = 0;
while(pStr[i]!='\0')
{
length++;
i++;
}
for (int i = 0; i < length / 2; i++) {
char temp = pStr[length - i - 1] ;
pStr[length - i - 1] = pStr[i];
pStr[i] = temp;
}
}
I am expecting it to reverse a string; I have a main function that uses it.
Strings in C are sequences of characters terminated with a zero character '\0'.
So this loop
while(pStr[i]!='\0')
{
length++;
i++;
}
calculates the length of the string that is how many characters there are in the string before the zero character. Instead of the loop you could use standard C function strlen declared in header <string.h>.
This loop
for (int i = 0; i < length / 2; i++) {
char temp = pStr[length - i - 1] ;
pStr[length - i - 1] = pStr[i];
pStr[i] = temp;
}
swaps character from the first half of the string with characters of the second half of the string. That is the first character is swapped with the last character, the second character is swapped with the before last character and so on until the middle of the string.
The function has several drawbacks. It could be written (without using standard C functions) the following way
#include <stdio.h>
char * ReverseString( char *pStr )
{
size_t n = 0;
// Calculates the number of characters in the string
// excluding the zero character.
// SO the variable n will contain the number of characters in the string.
while ( pStr[n] != '\0' ) ++n;
// Swaps characters from the first half of the string with
// the characters of the second half of the string.
// So the loop has only n / 2 iterations.
for ( size_t i = 0; i < n / 2; i++ )
{
char c = pStr[n - i - 1] ;
pStr[n - i - 1] = pStr[i];
pStr[i] = c;
}
return pStr;
}
int main( void )
{
char s[] = "Prachi Rajesh Jansari";
puts( s );
puts( ReverseString( s ) );
}
The program output is
Prachi Rajesh Jansari
irasnaJ hsejaR ihcarP

How to get rid of garbage characters in this program?

This program is supposed to print an input string backwards. Every single time it happens, though, I get garbage characters such as \340 or of the like. Why is it doing that? Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char mattsentence[51];
mattsentence[50] = '\0';
gets(mattsentence);
char mask[sizeof(mattsentence)];
int i, j;
j = sizeof(mattsentence);
for (i = 0; i < sizeof(mask); i++)
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
printf("\n");
}
Your approach is wrong because you reverse the entire character array while it can be filled only partially. You should use standard C function strlen declared in header <string.h> that to determine the size of the entered string. Also to use gets is unsafe because you can overwrite memory beyond the character array. It now is excluded from the C Standard
Here is shown how the program can be written.
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
char mask[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[--n] = '\0';
for ( size_t i = 0; n != 0; i++ )
{
mask[i] = mattsentence[--n];
printf( "%c", mask[i] );
}
printf( "\n" );
return 0;
}
If to enter
Hello, Christiana S. F. Chamon
then the program output will be
nomahC .F .S anaitsirhC ,olleH
Take into account that to output a string in the reverse order there is no need to define a second character array.
If you want only to output the source string in the reverse order then the program can look like
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[n-1] = '\0';
while ( n != 0 )
{
printf( "%c", mattsentence[--n] );
}
printf( "\n" );
return 0;
}
sizeof() operator gives the size of the datatype. So, sizeof(mattsentence) will give you a value of 51. Then, sizeof(mask) will give you 51 again.
When you use that sizeof(mask) as for loop condition, you're basically going past the actual input values, thus pritning out garbage values.
What you want here is to use strlen() to find out the actual valid length of the entered string.
So, basically you need to take care of
Point 1: replace sizeof with strlen().
Point 2: Use of gets() is dangerous. Please use fgets() instead of gets().
Point 3: int main() should be int main(void). Put an expilicit return statement at the end of main(). Good Practice.
The modified code should look like
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char mattsentence[51] = {0}; //always initalize local variables, here it's covering null termination , too.
fgets(mattsentence, 51, stdin); //fgets()
char mask[strlen(mattsentence) + 1]; // one more to store terminating '\0'
int i = 0, j = 0, k = 0;
j = strlen(mattsentence);
k = j;
for (i = 0; i < k; i++) // make use of k, don't call `strlen()` repeatedly
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
return 0; //added return statement
}
See changed code:
int main()
{
char mattsentence[51];
mattsentence[0] = '\0'; // initialization
gets(mattsentence);
char mask[strlen(mattsentence) + 1]; // +1 for string terminator '\0'
int i, j;
j = strlen(mattsentence);
for (i = 0; i < strlen(mattsentence); i++) // strlen of original string
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
}
There are several errors:
strlen() should be used to get length of string
for loop should be controlled according to input string, not output string
it is better to use fgets() instead of gets(): that way you can control how many character will be read from the input

Resources