I am trying to input a string of characters, and then output them backwards like
Input: Hello
Output: olleH
I have a working example, however I am getting every single letter except the last.
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
int main(void) {
int my_stg2[MAX_SIZE];
int i = 0;
int j;
char my_stg[MAX_SIZE];
int input ;
input = getchar();
while (input != '\n'){//The new line is the stopping point.
my_stg2[i] = input;
++i;
input = getchar();
}
for (j=0;i>=0;i--){
my_stg[j] = my_stg2[i];
j++;
}
printf("%s\n" , my_stg);
}
I tried the above code, however I am getting weird output with large strings. Can someone fix the loop for me? http://imgur.com/PK97b.png
Ok. In order to solve cases like this you should really do what Kristopher Johnson says and go through it on paper to figure out how your variables will change during the execution of your program. Pen and paper are some of the most important tools a programmer has.
Just because I know it can be hard to do this if you don't know how to do it, let me talk you through it.
Assume the input "Hello\n". Before you start looping you will have the following values:
i = 0 & input = 'H'
You then go on to loop:
while (input != '\n') { my_stg2[i] = input; ++i; input = getchar(); }
for each iteration in your loop, your values will change to be:
i = 1 & input = 'e' & my_stg2[0] = 'H'
i = 2 & input = 'l' & my_stg2[1] = 'e'
i = 3 & input = 'l' & my_stg2[2] = 'l'
i = 4 & input = 'o' & my_stg2[3] = 'l'
i = 5 & input = '\n' & my_stg2[4] = 'o'
So. i is now 5.
You now go on to the second loop, and you do the following:
for (j = 0; j <= i; j++) { --i; my_stg[i] = my_stg2[j]; }
you start to loop, and after having decremented i you have the following value pairs:
j = 0 & i = 5 & my_stg[4] = my_stg2[0] = 'H'
j = 1 & i = 4 & my_stg[3] = my_stg2[1] = 'e'
j = 2 & i = 3 & my_stg[2] = my_stg2[2] = 'l'
...and at the third step the loop stops. The output you get is "leH".
Now, why did the loop stop? Look over your conditions, and you'll find your answer.
Tweak your for loop as below
for (j=0; j < i; j++)
{
my_stg[i - (j + 1)] = my_stg2[j];
}
my_stg[i] = 0;
This is what you have
// The following line is pseudo-code.
// The '\0' is required in C to mark end of a character string.
orig := 'H', 'e', 'l', 'l', 'o', '\0'
with number of characters n = 6 (don't forget the \0).
Following is what you want to achieve
reverse := 'o', 'l', 'l', 'e', 'H', '\0'
So, this is what we have to do:
A. put a \0 in reverse[ n - 1 ]
B. We would read orig forward starting at index i = 0, and write to reverse backward starting at index j = n - 1. For that, we use two index variables:
i, for indexing orig, starting at 0 and incrementing up to n - 1
j, for indexing reverse, starting at n - 1 and decrementing down to 0
C. copy from orig[ i ] to reverse[ j ]
for( i = 0, j = n - 1; (i <= n - 1) && (j >= 0); ++i, --j ) {
reverse[ j ] = orig[ i ];
}
There are 2 mistakes with your program.
First, realize that the value of "i" in your first loop is always set to "the index we will next write into".
i = 0; input = getchar();
while (input != '\n'){
my_stg2[i] = input;
++i;
input = getchar();
}
Exiting that loop after writing "Hello!", you would have
my_stg2[] = {'H', 'e', 'l', 'l', 'o', '!'}, i=6
When you start reading the values out of my_stg2 you should therefore start reading from (i-1) instead of from i.
The second problem is that after copying the contents of my_stg2 to my_stg you need to do:
my_stg2[j] = 0;
This is because strings in C use a trailing null to determine the end of the string. The reason you get garbage characters following your string in the picture you attached is because the printf() code will keep printing each successive byte in memory until it reaches a 0, and you never placed a 0 at the end of the my_stg string explicitly.
Alternately you could initialize the entire contents of my_stg2 to 0 at the start of your program with
memset(my_stg2, 0x00, sizeof(my_stg2));
This is an important lesson with C - when you declare a variable you need to initialize it or it will on some platforms be filled with whatever was previously stored in the memory location.
You have several issues in your code:
int my_stg2[MAX_SIZE]; is an array of random ints when declared. These are of sizeof(int) on your platform -- probably 32 or 64 bits;
char my_stg[MAX_SIZE]; is a array of random characters when declared. These are of sizeof(char) on your platform -- probably 8 bits;
You are interchanging ints and characters with the assignment of my_stg[j] = my_stg2[i]; without a cast.
You are not checking for a buffer overrun in while loop. If someone typed more than MAX_SIZE characters before a \n, you will overrun the buffer you allocated;
You are not null terminating the string. If you are using getchar() that is a single character. You need to put a NUL after that or you will have a runaway string with the printf()
In your while loop, you need to check for EOF
It is counterintuitive, but getchar() is its own little loop like construct. It will not enter the while loop until an EOF or CR. It will then dump all the characters. You should not, then, test for CR against the getchar().
Your second loop is off by one; you are copying the value after the last character.
This code works as you expects I believe:
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
int main(void) {
char my_stg[MAX_SIZE], my_stg2[MAX_SIZE];
int i,j,input = 0;
while ((input=getchar())!=EOF) {
if(input=='\n' || i>=MAX_SIZE-1) break;
my_stg2[i++] = (char)input;
my_stg2[i+1] = (char)0l;
}
printf("my_stg2= %s\ni=%i\n",my_stg2,i);
for (j=0;i>0;i--,j++){
my_stg[j] = my_stg2[i-1];
my_stg[j+1]=(char)0l;
printf("i=%i %s\n",i,my_stg);
}
printf("%s\n" , my_stg);
return EXIT_SUCCESS;
}
Because it get a bit tedious to think about strings as having a NUL termination, most people use the standard C library for strings.
You may also want to ponder doing this loop more efficiently. Reversing a string in place using 1/2 the memory and 1/2 the steps with a recursive function like this:
void strrev ( char *buff, int start, int end )
{
char tmp ;
static int i=0;
if ( start >= end ) {i=0; return;}
printf("%i strrev=%s\n",++i,buff);
tmp = *(buff + start);
*(buff + start) = *(buff + end);
*(buff + end) = tmp ;
strrev (buff, ++start, --end );
}
If you look at the output, you can see it is 1/2 the steps and without copying to another buffer:
Hello World!!!
my_stg2= Hello World!!!
i=14
i=14 !
i=13 !!
i=12 !!!
i=11 !!!d
i=10 !!!dl
i=9 !!!dlr
i=8 !!!dlro
i=7 !!!dlroW
i=6 !!!dlroW
i=5 !!!dlroW o
i=4 !!!dlroW ol
i=3 !!!dlroW oll
i=2 !!!dlroW olle
i=1 !!!dlroW olleH
!!!dlroW olleH
Recursive:
1 strrev=!!!dlroW olleH
2 strrev=H!!dlroW olle!
3 strrev=He!dlroW oll!!
4 strrev=HeldlroW ol!!!
5 strrev=HelllroW od!!!
6 strrev=HelloroW ld!!!
7 strrev=Hello oWrld!!!
reverse the reverse: Hello World!!!
Have a look at a pointer backward-solution for your array question:
const char *loop = my_stg2 + strlen(my_stg2);
...
do {
my_stg[loop-my_stg2] = *loop;
} while( my_stg2 != loop-- );
Related
Why I am getting a space character in my program in the place of third last character?
Even if I change the string str variable I get the same result.
#include <stdio.h>
#include <string.h>
void parser(char array[])
{
int a, b;
for (int i = 0; i < strlen(array); i++) {
if (array[i] == '>') {
a = i;
break;
}
}
for (int j = a; j < strlen(array); j++) {
if (array[j] == '<') {
b = j;
}
}
for (int p = 0, q = a + 1; p < b - a - 1, q < b; p++, q++) {
array[p] = array[q];
array[b - a] = '\0';
printf("%c", array[p]);
}
}
int main()
{
char str[] = "<h1>hello there i am programmer.</h1>";
parser(str);
return 0;
}
There are many things that could be written better in the code but they do not affect the result.
The line that produces the unexpected outcome is:
array[b-a]='\0';
When this for loop starts...
for(int p=0,q=a+1;p<b-a-1,q<b;p++,q++){
array[p]=array[q];
array[b-a]='\0';
printf("%c",array[p]);
}
... the values of a and b are 3 and 32.
The statement array[b-a]='\0'; puts the NUL terminator character at position 29 in array.
The loop starts with p=0, q=4 (a+1) and repeats until p reaches 28 and q reaches 31 (q<b)*.
When p is 25, q is 29 and array[29] has been repeatedly set to '\0' on the previous iterations, therefore '\0' is copied at position 25 and printed on screen.
You should set the NUL terminator only once, after the loop. And the right position for it is b-a-1, not b-a; you expressed this correctly in the for initialization (p=0) and exit condition (p<b-a-1).
All in all, the code around the last for loop should be like this:
for(int p=0, q=a+1;q<b;p++,q++){
array[p]=array[q];
printf("%c",array[p]);
}
array[b-a-1]='\0';
*The condition p<b-a-1 is ignore because of the comma character. You probably want & between the conditions but they are equivalent, one of them is enough.
I am looking at a program that finds the frequency of strings entered. Comparison is made based on a string's ASCII value against the ASCII value of lowercase 'a'. I have implemented it; it works, albeit, with a bug, but essentially, I am ignorant of a particular line of code;
for (int i = 0; i < strlen(arr2); i++)
{
// this line...
arr1[ arr2[i] - 'a' ]++;
}
arr1 is arr1[26] = {0},
that is, all the letters of the alphabet are assigned an index and the array is initialised to zero, while arr2[] as a function argument, receives the stdin.
How does the mysterious line of code work and what is it saying?
The full code:
#include <stdio.h>
#include <string.h>
#define ALEPH 26
void freq(char arr2[]);
int main ()
{
char * str;
printf("\nCharacter Frequency\n"
"--------------------\n");
// user input
printf("\nEnter a string of characters:\n");
fgets(str, ALEPH, stdin);
freq(str);
return 0;
}
// Function Definiton
void freq (char arr2[])
{
// array for ascii characters initialised to 0
int arr1[ALEPH] = {0};
// scan and cycle through the input array
for (int i = 0; i < strlen(arr2); i++)
{
arr1[ arr2[i] - 'a' ]++;
}
for (int j = 0; j < 26; j++)
{
if ( arr1[j] != 0 )
{
printf("\nCharacter: %c - Frequency: %d", 'a'+j, arr1[j]);
}
}
printf("\n");
}
arr1 is an array of 26 ints initialized to 0s. The indexes of its elements are 0..25.
arr2 is assumed to be a string of lowercase letters 'a'..'z' only. The characters are assumed to be using an encoding where lowercase letters are single-byte and sequential in value, such as ASCII (where a=97, ..., z=122). Anything else that does not match these assumptions will cause undefined behavior in this code.
The code loops through arr2, and for each character, calculates an index by subtracting the numeric value of 'a' (ie, ASCII 97) from the character's numeric value:
'a' - 'a' = 97 - 97 = 0
'b' - 'a' = 98 - 97 = 1
...
'z' - 'a' = 122 - 97 = 25
Then the code accesses the arr1 element at that index, and increments that element's value by 1.
You ask about the line:
arr1[ arr2[i] - 'a' ]++;
In this line:
arr1 is the array that will accumulate the histogram
arr2 is the input string which will contribute to the histogram
i is the index into input string.
This can be rewritten as:
ch = arr2[i];
histogram_slot = ch - 'a';
arr1[histogram_slot ] = arr1[histogram_slot ] + 1;
For each character in the input string, the character is fetched from the string and assigned to "ch". "ch" is converted to the index in the histogram array by subtracting 'a'. In the third line, the histogram_slot is increased by one. histogram_slot 0 is incremented for 'a', 1 for 'b', 2 for 'c', ... , and 25 for 'z'.
A serious bug in this code is that it only works for the lower case letters. An upper case letter, digit, punctuation, Unicode, extended ASCII, or any character not between 'a' and 'z' inclusive will write in an unintended region of memory. At the best, this will cause an unexpected crash. In the medium disaster, it will cause sporatic malfunction that gets through your testing. In the worst case, it creates a security hole allowing someone uncontrolled access to your stack, and thus the ability to take over execution of the thread.
I am trying to create a character array with X number of characters.
I need the first X-1 characters to be spaces and I need the Xth character to be an *.
I have written the following:
int i = 0;
int X = 5;
char spaces[X]; //In this case X is 5 so the array should have indexes 0 - 4
for(i = 0; i < X; i++) {
spaces[i] = '*'; //I start by setting all 5 char's equal to '*'
printf("spaces = '%s'\n", spaces); //This was to make sure it ran the correct # of times
}
The output of this segment is the following, the 'gh' is different every time:
spaces = '*gh'
spaces = '**h'
spaces = '***'
spaces = '****'
spaces = '****'
why does spaces only grow to 4 instead of 5 characters?
Shouldn't spaces[4] = '*'; have been called?
After setting the whole string equal to '*' I run a second for loop:
for(i = 0; i < X-1; i++) {
spaces[i] = ' ';
}
which should then set everything but the Xth character equal to ' ', but since the string is acting like its only X-1 characters long, the whole thing is set to spaces and it comes out like this
spaces = ' ';
4 spaces, when I need 4 spaces followed by an *.
You are missing the string termination character \0, which is needed once you want to print your array as a string using printf("%s",...).
So make your array one item larger than the items you want to print, and initialize it with 0, such that everything you write into the array will at the end be a valid string. Otherwise you yield undefined behaviour:
int main (void)
{
#define X 5
int i = 0;
char spaces[X+1] = { 0 };
for(i = 0; i < X; i++) {
spaces[i] = '*';
printf("spaces = '%s'\n", spaces);
}
}
In order to set first X-1 characters to be spaces and the Xth character to be an .
This will always have the last character a ''
for(i = 0; i < X-1; i++) {
spaces[i] = ' ';
spaces[i+1] = '*';
printf("spaces = '%s'\n", spaces);
}
I was doing a program to copy all string words other than its first 2 words and putting a x at the end of it.
However i cant put x at its end. Please help!!!!
Below is my code.
#include<stdio.h>
#include<string.h>
int main()
{
char a[25], b[25];
int i, j, count = 0, l, k;
scanf("%[^\n]s", a);
i = strlen(a);
if (i > 20)
printf("Given Sentence is too long.");
else
{/* checking for first 2 words and counting 2 spaces*/
for (j = 0; j < i; j++)
{
if (a[j] == ' ')
count = count + 1;
if (count == 2)
{
k = j;
break;
}
}
/* copying remaining string into new one*/
for (j = 0; j < i - k; j++)
{
b[j] = a[j + k];
}
b[j + 1] = 'x';
printf("%s", b);
}
}
you are removing first two index. But you wrote k=j and if you check the current value j there it's 1. so you are updating wrongly k because you removed 2 indexes. So k value should be 2. So checked the below code
/* copying remaining string into new one*/
for (j = 0; j < i - 2; j++)
{
b[j] = a[j + 2];
}
b[j + 1] = 'x';
printf("%s", b);
Your index is off by one. After your second loop, the condition j < i-k was false, so j now is i-k. Therefore, the character after the end of what you copied is b[j], not b[j+1]. The correct line would therefore be b[j] = 'x';.
Just changing this would leave you with something that is not a string. A string is defined as a sequence of char, ending with a '\0' char. So you have to add b[j+1] = 0; as well.
After these changes, your code does what you intended, but still has undefined behavior.
One problem is that your scanf() will happily overflow your buffer -- use a field width here: scanf("%24[^\n]", a);. And by the way, the s at the and doesn't make any sense, you use either the s conversion or the [] conversion.
A somewhat sensible implementation would use functions suited for the job, like e.g. this:
#include<stdio.h>
#include<string.h>
int main(void)
{
// memory is *cheap* nowadays, these buffers are still somewhat tiny:
char a[256];
char b[256];
// read a line
if (!fgets(a, 256, stdin)) return 1;
// and strip the newline character if present
a[strcspn(a, "\n")] = 0;
// find first space
char *space = strchr(a, ' ');
// find second space
if (space) space = strchr(space+1, ' ');
if (space)
{
// have two spaces, copy the rest
strcpy(b, space+1);
// and append 'x':
strcat(b, "x");
}
else
{
// empty string:
b[0] = 0;
}
printf("%s",b);
return 0;
}
For functions you don't know, google for man <function>.
In C strings are array of chars as you know and the way C knows it is end of the string is '\0' character. In your example you are missing at the last few lines
/* copying remaining string into new one*/
for(j=0;j<i-k;j++)
{
b[j]=a[j+k];
}
b[j+1]='x';
printf("%s",b);
after the loop ends j is already increased 1 before it quits the loop.
So if your string before x is "test", it is like
't', 'e', 's', 't','\0' in char array, and since your j is increased more than it should have, it gets to the point just right of '\0', but characters after '\0' doesnt matter, because it is the end, so your x will not be added. Simple change to
b[j]='x';
For class, I am required to create a function that converts an Integer into it's corresponding Binary number. However, I am forced to use the given main and parameters for the to_binary function. The whole problem requires me to print out the 32 bit binary number, but to break it up, I am just trying to print out the Char Array, that I thought I filled with Integers (perhaps the issue). When I do compile, I receive just a blank line (from the \n) and I am wondering how I can fix this. All I want to do is to be able to print the binary number for 5 ("101") yet I can't seem to do it with my professor's restrictions. Remember: I cannot change the arguments in to_binary or the main, only the body of to_binary. Any help would be greatly appreciated.
#include<stdio.h>
void to_binary(int x, char c[]) {
int j = 0;
while (x != 0) {
c[j] x = x % 2;
j++;
}
c[33] = '\0';
}
int main() {
int i = 5;
char b[33];
to_binary(i,b);
printf("%s\n", b);
}
This is the answer to your question.
void to_binary(int x, char c[]) {
int i =0;
int j;
while(x) {
/* The operation results binary in reverse order.
* so right-shift the entire array and add new value in left side*/
for(j = i; j > 0; j--) {
c[j] = c[j-1];
}
c[0] = (x%2) + '0';
x = x/2;
i++;
}
c[i]=0;
}
the problem is in the code below:
while (x != 0) {
c[j] = x % 2; // origin: c[j] x = x % 2; a typo?
j++;
}
the result of x % 2 is a integer, but you assigned it to a character c[j] —— integer 1 is not equal to character '1'.
If you want to convert a integer(0-9) to a character form, for example: integer 7 to character '7', you can do this:
int integer = 7;
char ch = '0' + integer;
One of the previous answers has already discussed the issue with c[j] x = x % 2; and the lack of proper character conversion. That being said, I'll instead be pointing out a different issue. Note that this isn't a specific solution to your problem, rather, consider it to be a recommendation.
Hard-coding the placement of the null-terminator is not a good idea. In fact, it can result in some undesired behavior. Imagine I create an automatic char array of length 5. In memory, it might look something like this:
Values = _ _ _ _ _
Index = 0 1 2 3 4
If I were to populate the first three indexes with '1', '0', and '1', the array might look like so:
Values = 1 0 1 _ _
Index = 0 1 2 3 4
Let's say I set index 4 to contain the null-terminator. The array now looks like so:
Values = 1 0 1 _ \0
Index = 0 1 2 3 4
Notice how index three is an open slot? This is bad. In C/C++ automatic arrays contain garbage values by default. Furthermore, strings are usually printed by iterating from character to character until a null-terminator is encountered.
If the array were to look like it does in the previous example, printing it would yield a weird result. It would print 1, 0, 1, followed by an odd garbage value.
The solution is to set the null-terminator directly after the string ends. In this case, you want your array to look like this:
Values = 1 0 1 \0 _
Index = 0 1 2 3 4
The value of index 4 is irrelevant, as the print function will terminate upon reading index 3.
Here's a code example for reference:
#include <stdio.h>
int main() {
const size_t length = 4;
char binary[length];
size_t i = 0;
while (i < length - 1) {
char c = getchar();
if (c == '0' || c == '1')
binary[i++] = c;
}
binary[i] = '\0';
puts(binary);
return 0;
}
#include<stdio.h>
int binary(int x)
{
int y,i,b,a[100];
if(x<16)
{
if(x%2==1)
a[3]=1;
if(x/2==1||x/2==3 || x/2==5 || x/2==7)
a[2]=1;
if(x>4 && x<8)
a[1]=1;
else if(x>12 && x<16)
a[1]=1;
if(x>=8)
a[0]=1;
}
for(i=0;i<4;i++)
printf("\t%d",a[i]);
printf("\n");
}
int main()
{
int c;
printf("Enter the decimal number (less than 16 ):\n");
scanf("%d",&c);
binary(c);
}
this code might help it will simply convert the decimal number less than 16 into the 4 digit binary number.if it contains any error than let me know