I wrote code to reverse an array after in C.
I'm using C17. In the code the user is asked to input a word, the word then is put into an array
and then reversed.
The code works for the exception that it adds some random characters and I couldn't figure out why it does that.
Can you help me with that?
Here is my code
#include <stdio.h>
#define MAXLINE 80
void inputtoarray(char input[]); //Take the input from user and put it into an array
void reverseinput(char input1[]);
int main(){
char input[MAXLINE];
inputtoarray(input);
reverseinput(input);
return 0;
}
void inputtoarray(char input[]){
int c; //to hold the indiviual characters before going into the array
//int was used over char because I want to be able to hold EOF
int i; //i is the array counter
//ask the user to type in a word
printf("Please type in a word:\n");
for(i=0; (c=getchar()) != '\n'; ++i){
input[i] = c;
}
}
void reverseinput(char input1[]){
int cinput;
int coutput;
char temp[MAXLINE]; //define a temporary array
//count the number of characters in the array
for (cinput=0; input1[cinput] != '\0'; ++cinput){
}
coutput=cinput;
//the reversing process. Here cinput holds the number of the last character
for (cinput=0; coutput > 0; --coutput, ++cinput ){
temp[coutput] = input1[cinput];
//input1[coutput] = temp[coutput];
//printf("%s", temp);
}
input1 = temp;
printf("%s", input1);
}
The function inputtoarray does not input a string. As a result this loop
for (cinput=0; input1[cinput] != '\0'; ++cinput){
}
within the function reverseinput results in undefined behavior.
The function inputtoarray can look for example the following way
void inputtoarray( char input[], size_t n )
{
int c; //to hold the indiviual characters before going into the array
//int was used over char because I want to be able to hold EOF
size_t i = 0; //i is the array counter
//ask the user to type in a word
printf("Please type in a word:\n");
for ( ; i + 1 < n && ( c = getchar() ) != EOF && c != '\n'; ++i )
{
input[i] = c;
}
input[i] = '\0';
}
and called like
inputtoarray( input, MAXLINE );
Moreover this loop
for (cinput=0; coutput > 0; --coutput, ++cinput ){
temp[coutput] = input1[cinput];
//input1[coutput] = temp[coutput];
//printf("%s", temp);
}
does not set the element temp[0] due to the condition coutput > 0. So the first element of the array temp has an indeterminate value.
And this assignment
input1 = temp;
does not make a sense because it changes the local variable input instead of changing the array pointed to by the pointer (parameter) input.
Without using standard string functions the program can look the following way.
#include <stdio.h>
#define MAXLINE 80
void inputtoarray( char input[], size_t n )
{
int c; //to hold the indiviual characters before going into the array
//int was used over char because I want to be able to hold EOF
size_t i = 0; //i is the array counter
//ask the user to type in a word
printf("Please type in a word:\n");
for ( ; i + 1 < n && ( c = getchar() ) != EOF && c != '\n'; ++i )
{
input[i] = c;
}
input[i] = '\0';
}
void reverseinput( char input[] )
{
size_t n = 0;
while ( input[n] ) ++n;
if ( n != 0 )
{
for ( size_t i = 0; i < --n; i++ )
{
char c = input[i];
input[i] = input[n];
input[n] = c;
}
}
}
int main(void)
{
char input[MAXLINE];
inputtoarray( input, MAXLINE );
reverseinput( input );
puts( input );
return 0;
}
Its output might look like
Please type in a word:
Hello
olleH
Related
I'm doing the exercises from C Programming Language, the one where you need to make a function to reverse a line. So I did and it works sometimes. But only some times. With the same test it gives different results. I really don't get it, and would appreciate some help. 3 tries out of 4 it would print around 150 spaces and 1 out of 4 it would print the reversed line just like I wanted, though with some junk in the end for some reason.
I was thinking of doing it with pointers, but couldn't figure them out as of now.
Here's my code:
#include <stdio.h>
void reverse(char theline[150]){
int i, j;
char tmp[150];
for (i = 0; theline[i] != 0; i++){
tmp[i] = theline[i];
}
for (j = 0; i >= 0; j++){
theline[j] = tmp[i];
i--;
}
}
int main() {
char line[150];
char c;
int counter = 0;
do {
counter = 0;
while (((c = getchar()) != '\n') && (c != EOF)) { //one line loop
line[counter] = c;
counter++;
}
if (counter > 80){
reverse(line);
printf("%s\n", line);
}
}
while (c != EOF);
return 0;
}
I compile it with "gcc -g -Wall program -o test" and the compiler doesn't give me any errors or warnings. My OS is Ubuntu and I test it with "./test < longtext.txt". This text file has a few lines of different length.
After this loop
while (((c = getchar()) != '\n') && (c != EOF)) { //one line loop
line[counter] = c;
counter++;
}
the character array line does not contain a string because the stored characters are not appended with the terminating zero character '\0'.
So this loop within the function
for (i = 0; theline[i] != 0; i++){
tmp[i] = theline[i];
}
invokes undefined behavior.
You need to append the array with the terminating zero character '\0'.
But even if the passed character array will containe a string the second for loop
for (i = 0; theline[i] != 0; i++){
tmp[i] = theline[i];
}
for (j = 0; i >= 0; j++){
theline[j] = tmp[i];
i--;
}
writes the terminating zero character '\0' in the first position if the array theline. As a result you will get an empty string.
Also the function shall not use the magic number 150 and an auxiliary array.
Pay attention to that the variable c should be declared as having the type int. In general the type char can behave either as the type signed char or unsigned char depending on compiler options. If it will behave as the type unsigned char then this condition
c != EOF
will always evaluate to true.
Without using standard C string functions the function can be declared and defined the following way
char * reverse( char theline[] )
{
size_t i = 0;
while ( theline[i] != '\0' ) i++;
size_t j = 0;
while ( j < i )
{
char c = theline[j];
theline[j++] = theline[--i];
theline[i] = c;
}
return theline;
}
Here is a demonstration program
#include <stdio.h>
char * reverse( char theline[] )
{
size_t i = 0;
while ( theline[i] != '\0' ) i++;
size_t j = 0;
while ( j < i )
{
char c = theline[j];
theline[j++] = theline[--i];
theline[i] = c;
}
return theline;
}
int main( void )
{
char s[] = "Hello World!";
puts( s );
puts( reverse( s ) );
}
The program output is
Hello World!
!dlroW olleH
Why muck-around with reversing a buffer when you can simply store-up the entered characters as they arrive.
#include <stdio.h>
int main() {
for( ;; ) {
char line[ 150 ];
int c, counter = sizeof line;
line[ --counter ] = '\0';
// NB: EOF is an int, not a char
while( ( c = getchar() ) != '\n' && c != EOF && counter > 0 )
line[ --counter ] = (char)c;
printf( "%s\n\n", line + counter );
counter = sizeof line;
}
return 0;
}
Output:
the quick
kciuq eht
Once upon a time in a land far awy
ywa raf dnal a ni emit a nopu ecnO
I wish I was what I was when I wished I was what I am now.
.won ma I tahw saw I dehsiw I nehw saw I tahw saw I hsiw I
I'm trying to solve exercise 1-19 in K&R C second edition. "Write a function reverse that reverses the character string s. Use it to write program that reverses its input a line at a time."
My solution takes two input strings s and t. s is source and t is target. And it copies the data in source s to t. I'm able to solve the problem, but I'm struggling hard to understand why would source string s be modified, even though it is not on the left hand side of the equal operator.
#include <stdio.h>
/* Solution to Exercise 1-19. Chapter 1 */
#define MAXLENGTH 10
int getln(char s[], int lim);
void reverse(char s[], char t[]);
int main()
{
int i, len;
char s[MAXLENGTH]; /* original string */
char t[MAXLENGTH]; /* reversed string */
while ((len = getln(s, MAXLENGTH)) > 0) {
printf("before reverse: %s", s);
reverse(s,t);
printf("reversed string: %s\n", t);
printf("after reverse: %s", s);
}
return 0;
}
/* getln: read a line into s, return length */
int getln(char s[], int lim)
{
int c, i, l;
l = 0;
for (i = 0; ((c = getchar()) != EOF) && (c != '\n'); ++i) {
if (i < (lim - 1)) {
s[l] = c;
++l;
}
}
if (c == '\n') {
s[l] = c;
++l;
}
s[l] = '\0';
return l;
}
/* reverse: reverses s to target t */
void reverse(char s[], char t[])
{
int i, j;
for (i = 0; s[i] != '\0'; ++i)
;
--i;
if (s[i] == '\n') {
--i;
}
for (j = 0; i >= 0; ++j) {
t[j] = s[i];
--i;
}
t[j] = '\0';
}
Test case:
$ ./a.out < testdata
before reverse: abcdefghi
reversed string: ihgfedcba
after reverse: abcdefghi
ihgfedcba$
Contents of file testdata:
$ cat testdata
abcdefghijklmnopqrstuvwxyz
$
There is a bug in the function getln To simplify the analyze of the function let's assume that lim is equal to 2.
Then in this loop
l = 0;
for (i = 0; ((c = getchar()) != EOF) && (c != '\n'); ++i) {
if (i < (lim - 1)) {
s[l] = c;
++l;
}
}
you can write lim-1 characters that is only one character. The loop stops its iterations when the user will press the key Enter that sends to the input buffer the new line character '\n'.
So the last read character is the new line character '\n'. This character is stored in the string after the loop
if (c == '\n') {
s[l] = c;
++l;
}
Now the limit is exhausted. Two characters of the passed character array are set.
However in the next statement
s[l] = '\0';
there is access to the memory beyond the limit when l is equal to 2.
That is all. The function invokes undefined behavior provided that the value of the parameter lim is equal to the size of the passed character array. The terminating zero character '\0' is written in the memory outside the character array and later can be overwritten.
I would define the function the following way as it is shown in the demonstrative program below.
#include <stdio.h>
size_t getln( char s[], size_t n )
{
size_t i = 0;
if ( n )
{
int c;
while ( i + 1 < n && ( c = getchar() ) != EOF && c != '\n' )
{
s[i++] = c;
}
if ( c == '\n' && i + 1 < n ) s[i++] = c;
s[i] = '\0';
}
return i;
}
int main(void)
{
enum { N = 10 };
char s[N];
while ( getln( s, N ) ) printf( "\"%s\"\n", s );
return 0;
}
If to enter
abcdefghijklmnopqrstuvwxyz
then the program output will be
"abcdefghi"
"jklmnopqr"
"stuvwxyz
"
That is only the last entered string contains the new line characters.
Pay attention to that in the exercise there is written
Write a function reverse that reverses the character string s.
This means that you need to reverse the original string itself instead of coping it in the reverse order to another character array.
Such a function can look the following way
#include <stdio.h>
char * reverse( char *s )
{
size_t n = 0;
while ( s[n] != '\0' ) n++;
if ( n && s[n-1] == '\n' ) --n;
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n-i-1];
s[n-i-1] = c;
}
return s;
}
size_t getln( char s[], size_t n )
{
size_t i = 0;
if ( n )
{
int c;
while ( i + 1 < n && ( c = getchar() ) != EOF && c != '\n' )
{
s[i++] = c;
}
if ( c == '\n' && i + 1 < n ) s[i++] = c;
s[i] = '\0';
}
return i;
}
int main(void)
{
enum { N = 10 };
char s[N];
while ( getln( s, N ) ) printf( "\"%s\"\n", reverse( s ) );
return 0;
}
Again if the input is
abcdefghijklmnopqrstuvwxyz
then the program output is
"ihgfedcba"
"rqponmlkj"
"zyxwvuts
"
If you want to remove the new line character '\n' from the string inside the function reverse then substitute this statement
if ( n && s[n-1] == '\n' ) --n;
for this one
if ( n && s[n-1] == '\n' ) s[--n] = '\0';
You are not allocating memory for c or t, therefore you are overwriting things.
I was trying to write a program that reverses its input a line at a time. I thought I had done it successfully, however it sometimes doesn't give the desirable output (this happens when I put an input with a smaller length than the one I put previously). I am new to this and I was wondering what can I do to solve this issue.
Program:
#include <stdio.h>
#define MAXLINE 1000
void reverse(char o[], char l[]);
int mgetline(char line[]);
int main(void){
int len;
char line[MAXLINE];
char rev[MAXLINE];
while((len = mgetline(line)) > 0){
reverse(rev, line);
printf("%s\n",rev);
}
return 0;
}
int mgetline(char s[])
{
int c,i;
for(i = 0; ((c=getchar())!=EOF) && (c!='\n'); ++i)
s[i] = c;
if (c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
void reverse(char revi[], char liner[])
{
int i, c, j;
for(i=0;liner[i]!='\0';++i)
;
--i;
if(liner[i]=='\n')
--i;
for(j=0; j<=i ; ++j){
c = i - j;
revi[j] = liner[c];
}
--j;
}
Since you not terminating the revi string at the end, therefore it will print the leftout characters from the previous result if the new input is smaller. Fix it by adding this
revi[j] = '\0';
at the end of the reverse function and delete that last --j;.
The function reverse does not build a string that is it does not append the terminating zero '\0' to the result string.
The second parameter of the function should have the qualifier const because it is not changed in the function.
As all standard C string functions this function should return pointer to the result string.
And it is better to name the function like reverse_copy instead of reverse because the name reverse is usually used when a container is reversed "in place".
It can look the following way
char * reverse_copy( char revi[], const char liner[] )
{
size_t n = 0;
while ( liner[n] ) ++n;
if ( n != 0 && liner[n-1] == '\n' ) --n;
size_t i = 0;
while ( n != 0 ) revi[i++] = liner[--n];
revi[i] = '\0';
return revi;
}
I'm getting random characters after the actual output in printf("%s",result);.
Why are these characters being printed? And how can I remove them?
#include<stdio.h>
char *replacechar(char[]);
int main()
{
char str[25];
char *result;
int i=0;
while( (str[i++]=getchar()) != '\n' && i < 25);
result= replacechar(str);
printf("%s",result);
return 0;
}
char *replacechar(char str[])
{
return str;
}
Expected Output:
aaayt
aaayt
Actual Output:
aaayt
aaayt
↑#
For starters the operands of the condition
(str[i++]=getchar()) != '\n' && i < 25
should be swapped.
i < 25 && (str[i++]=getchar()) != '\n'
The input stored in the character array str should be zero-terminated. Otherwise the array will not contain a string.
Here is a demonstrative program that shows how your code can be rewritten
#include <stdio.h>
char *replacechar( char str[] )
{
return str;
}
int main(void)
{
enum { N = 25 };
char str[N];
char *result;
size_t i = 0;
while( i < N - 1 && ( str[i] = getchar() ) != '\n' ) i++;
str[i] = '\0';
result = replacechar( str );
puts( result );
return 0;
}
Its output might look like
Hello Siddharth Awana
Hello Siddharth Awana
I need to write a C program that counts the number of characters and digits in a file. I believe my best attempt is close, but the program must call a given function, mostfrequent(), and I cannot figure out how to implement it into my main so that they work together. Any help would be greatly appreciated. Thank you.
// this is the function my program is required to use.
int mostfrequent(int *a, int length) {
int index = 0;
int max = a[0];
int i;
for (i = 1; i < length; i++) {
if (a[i] > max) {
max = a[i];
index = i;
}
}
return index;
}
// this is my closest attempt at a working program so far, but it does
// not call mostfrequent() which I need it to do.
int main() {
typedef FILE *ptr_file;
int x, i, j;
int length;
char c;
char ch[1000];
int a = 65;
c = getc(ptr_file);
ptr_file = fopen("file.txt", "r");
if (!ptr_file)
return 1;
while (c != EOF) {
scanf(ptr_file, "%s", ch[i]);
i++;
fclose(ptr_file);
}
for (i = 0; i < length; i++) {
for (j = 0; j < length; j++) {
if (a < 116) {
if (char(a) == 'ch[j]')
char max_char_temp=(char)a
count_temp++;
}
if (count_temp > count) {
count = count_temp;
max_char = max_char_temp;
}
return 0;
}
regarding the question: when to call the most_frequent() function.
After you have created an array (which would be 36 entries long of integers), initialize that array to all zeros, then incremented the appropriate entry for each character read from the input file. (note 36 entries allows for a...z + 0...9 so all other characters read from the file should be discarded.
Then pass the array and 36 to the most_frequent() function
then code similar to the following could do the job:
#include <stdio.h>
#include <stdlib.h>
#include <ctypes.h> // isalpha(), isdigit(), toupper()
#define NUM_ALPHA (26)
int main( void )
{
int array[36] = {'\0'};
//...open file, etc
//then assure all processed characters are upper case or numeric
// and update the count in the array
int ch;
while( ch = getc( file ) != EOF && '\n' != ch)
{
if ( isalpha(ch) )
{
ch = toupper(ch);
array[ch - 'A']++;
}
else if (isdigit(ch) )
{
array[ (ch-'0') + NUM_ALPHA ]++;
}
}
int index = mostfrequent( array, sizeof(array)/sizeof(array[0]);
//... do what is needed with 'index' for instance
printf( "the highest occurring char is:" );
if( index < NUM_ALPHA )
{
printf( "%c\n", index+'A' );
}
else
{
printf( "%d\n", (index-NUM_ALPHA)+'0');
}
fclose( file );
return 0;
}
however, note that mostfrequent() only returns the index to the first entry encountered with the max value, when there are multiple entries with the same max value.