I'm trying to convert a string from upper case to lower case to check if it is a palindrome, however I keep getting the error:
"function declaration is not a prototype"
I already added #include <string.h> in the header, but it still doesn't work. How do I get around this issue?
This is the code:
int main (void)
{
char *user_string, *user_string_rev;
/* the malloc function is used to make sure that enough memory is allocated for the string and that it does not overwrite memory boxes of other variables. */
user_string= (char*)malloc(BUFF_SIZE*sizeof(char));
user_string_rev= (char*)malloc(BUFF_SIZE*sizeof(char));
printf("Please enter a string:");
fgets(user_string,BUFF_SIZE, stdin); /* fgets function take the string the user inputs and stores it into user_string. */
user_string_rev=strcpy(user_string_rev, user_string); /*the strcpy takes the string the user inputs and copies it to user_string_rev. */
strlwr(user_string_rev);
palindrome_check(user_string,user_string_rev); /*this is the palindrome function used to check if the two strings are palindromes, it intakes two arguments, the two strings and does not return anything. */
return 0;
}
Replace :
strlwr(user_string_rev);
which is not a standard function with:
int i = 0;
while (user_string_rev[i])
{
if (isalpha(user_string_rev[i]))
user_string_rev[i] |= 32;
++i;
}
Don't forget to add the ctype header at the top of your .c file to use isalpha:
#include <ctype.h>
the following proposed code:
incorporates the comments to the question
cleanly compiles
properly checks for errors
will treat a string that is nothing but a newline as NOT a palindrome
And now the proposed code:
#include <stdio.h> // getline(), printf()
#include <stdlib.h> // free()
#include <ctype.h> // tolower()
#include <string.h> // strlen(), strchr()
// prototypes
void palindrome( char *, size_t length );
int main( void )
{
char *inputStr = NULL;
size_t lengthStr = 0;
printf("Please enter a string:");
if( -1 != getline( &inputStr, &lengthStr, stdin ) )
{
size_t length = strlen( inputStr );
for( size_t i = 0; i < length; i++ )
{
inputStr[i] = (char)tolower( inputStr[i] );
}
char *newline = strchr( inputStr, '\n' );
if( newline )
{
*newline = '\0';
length--;
}
palindrome( inputStr, length );
}
free( inputStr );
return 0;
}
void palindrome( char stringToCheck[], size_t length )
{
size_t index = length - 1; // don't check NUL terminator byte
size_t i;
for( i = 0; i < index; i++ )
{
if( stringToCheck[i] != stringToCheck[ index ] )
{
break;
}
index--;
}
if( i < index )
{
printf( "%s is not a palindrome\n", stringToCheck );
}
else
{
printf( "%s is a palindrome\n", stringToCheck );
}
}
Related
I have a task to do. I have to work with strings. I will show you the input and output, because I think that will be clear what the task is.
Input: "aaa bbuvvvvo"
Output: "a$3 b$2uv$4o"
If there is the same symbols, I have to leave that symbol and then put dollar sign '$' and an integer of how many same signs was there. I am stuck on the spot, where I have to change string without losing any information.
I will leave my code here, it might help.
#include <stdio.h>
#include <string.h>
#define CAPACITY 255
#define MAX_NUMBER 10
void Output(char readFile[], char outputFile[], char string[]);
void changeString(char string[], char newString[]);
int main() {
char readFile[CAPACITY];
char outputFile[CAPACITY];
char string[CAPACITY];
// Input file's name
printf("Iveskite teksto failo varda: ");
scanf("%s", &readFile);
// Output file's name
printf("Iveskite teksto faila i kuri bus isvedamas atsakymas: ");
scanf("%s", &outputFile);
Output(readFile, outputFile, string);
return 0;
}
// Scanning file
void Output(char readFile[], char outputFile[], char string[])
{
char newString[CAPACITY];
FILE *input, *output;
input = fopen(readFile, "r");
while(fscanf(input, "%s", string) != EOF)
{
changeString(string, newString);
printf("%s\n", newString);
}
}
// Changing string to wanted string
void changeString(char string[], char newString[])
{
char number[MAX_NUMBER];
int symbols = 0;
int j;
for(int i = 0; string[i] != '\0'; ++i)
{
int temp = i;
newString[i] = string[i];
if(newString[i] == string[i + 1])
{
j = i;
while(string[j] == string[i])
{
++symbols;
++j;
}
// Changing int to char
sprintf(number, "%d", symbols);
newString[i + 1] = '$';
i += 2;
newString[i] = number[0];
symbols = 0;
}
}
}
I have tried to do that with function called changeString, but I get the wrong output all the time. Also the input I am getting is from .txt file.
EDIT: When I compiling this program right now, I get a$3 b$2v$4vo that output.
For starters this declaration in main
char string[CAPACITY];
does not make sense.
You should declare variables in scopes where they are used.
The variable string is used in the function Output where it is should be declared.
The function changeString should be declared like
void changeString( const char string[], char newString[]);
because the source string is not changed within the function.
Your function has several bugs.
For example it does not build a string in the array newString because it does not append the stored sequence in the array with the terminating zero character '\0'.
Secondly this increasing of the variable i
i += 2;
in general is invalid. You need to add to the variable i the number of repeated characters in the source string.
Or the number of repeated characters change greater than or equal to 10. In this case this statement
newString[i] = number[0];
will not produce correct result.
The function can be defined the following way as shown in the demonstration program below.
#include <stdio.h>
#define CAPACITY 255
void changeString( const char string[], char newString[] )
{
while ( *string )
{
*newString++ = *string;
size_t n = 1;
while (*++string == *( newString - 1 ) ) ++n;
if (n != 1)
{
*newString++ = '$';
int count = sprintf( newString, "%zu", n );
newString += count;
}
}
*newString = '\0';
}
int main( void )
{
char string[CAPACITY] = "aaa bbuvvvvo";
char newString[CAPACITY];
changeString( string, newString );
puts( newString );
}
The program output is
a$3 b$2uv$4o
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int a[100];
char mi[200];
char delims[] = "\040";
char * li;
fgets(mi,200,stdin);
li = mi;
li = strtok(li,delims);
a[0] = atoi(li);
for(int i=1;li!=NULL;i++)
{
li = strtok(NULL,delims);
a[i] = atoi(li);
}
return 0;
}
all the input were separate by space.
I wrote one,but it's so complex,so I wonder if there is an easier way.
That is pretty much how it needs to be done, although you have a small problem with your tokenizing loop: think about what will happen when there are no more tokens remaining. I would recommend using more meaningful variable names, to make code more self-documenting.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int values[100];
char linebuf[200];
char *token;
fgets(linebuf,sizeof(linebuf),stdin);
token = strtok(linebuf,' ');
for(int i = 0; token; i++) {
values[i] = atoi(token);
token = strtok(NULL,' ');
}
return 0;
}
If it were my code, I might prefer to use strtol instead of atoi, to be able to have some more error checking to screen out extraneous (non-numerical) characters.
If you use strtol instead of atoi, you don't need to use strtok. The function strtol will automatically discard all leading whitespace characters and will tell you the first character that it didn't convert, so you know where to continue.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NUMBERS 100
int main(void)
{
long numbers[MAX_NUMBERS];
char line[200];
char *p;
fgets( line, sizeof line, stdin );
p = line;
for ( int i = 0; i < MAX_NUMBERS; i++ )
{
long ret;
char *q;
numbers[i] = strtol( p, &q, 10 );
if ( p == q )
break;
p = q;
}
return 0;
}
If you do proper error checking, and print the result, the code will look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define MAX_NUMBERS 100
int main(void)
{
long numbers[MAX_NUMBERS];
int num_converted;
char line[200];
char *p;
int i;
//attempt to read one line of input
if ( fgets( line, sizeof line, stdin ) == NULL )
{
fprintf( stderr, "error reading line!" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read
if ( strchr( line, '\n' ) == NULL )
{
fprintf( stderr, "input line was too long!" );
exit( EXIT_FAILURE );
}
//begin at the start of the line
p = line;
for ( i = 0; i < MAX_NUMBERS; i++ )
{
long ret;
char *q;
//attempt to convert one number
errno = 0;
numbers[i] = strtol( p, &q, 10 );
//break loop if it was unable to convert another number
if ( p == q )
break;
//verify that the found number is not out of range
if ( errno == ERANGE )
{
fprintf( stderr, "number out of range!" );
exit( EXIT_FAILURE );
}
//continue after the converted number
p = q;
}
//remember how many numbers were converted
num_converted = i;
//print how many numbers were converted
printf( "Converted %d numbers:\n", i );
//print all the converted numbers
for ( i = 0; i < num_converted; i++ )
printf( "%ld\n", numbers[i] );
return 0;
}
If you run this code with the input 761 87 2387, followed by a newline character, then the output will be the following:
Converted 3 numbers:
761
87
2387
I am trying to write code for String Obfuscation but it gives me Abort trap: 6 error while running. Any ideas are much appreciated:
#include <stdio.h>
#include <math.h>
#include <string.h>
char* readLine_str_test_encrypt();
char* readLine_str_test_decrypt();
int main () { //body
printf("%s\n", readLine_str_test_encrypt());
printf("%s\n", readLine_str_test_decrypt());
}
char* readLine_str_test_decrypt() {
static unsigned char string[9] = {100, 115, 119, 114, 90, 127, 120, 115, 22};
static int i = 0;
for (; i < 9; ++i) {
string[i] ^= 22;
}
return (char*)string;
}
char* readLine_str_test_encrypt()
{
static unsigned char string[9] = "readLine";
char output[9];
char* output_start=output;
static int i =0;
for(; i < 9; ++i)
{
//string[i] = string[i]^22;
output_start += sprintf(output_start,"%d",string[i]^22);
}
return output_start;
}
My decrypt function is running successfully.
In the readLine_str_test_encrypt you are returning a pointer to variable output. This variable is a local variable and goes out of scope when the function exits.
Change it to
static char output[9];
and the error goes away.
Read more as to why you should not return a local variable here.
the posted code is:
including a header file those contents are not used
trying to 'sprintf()` a 3 char integer into a single byte
returning pointers to local variables
is not terminating the strings to be printed with a NUL byte
Note: size_t is a well known definition for unsigned long int
The following suggested code corrects all of the above problems and a few others.
#include <stdio.h> // printf()
#include <stdlib.h> // exit(), EXIT_FAILURE, malloc(), free()
//#include <math.h>
#include <string.h> // strlen()
char* readLine_str_test_encrypt( char *, size_t );
char* readLine_str_test_decrypt( char *, size_t );
int main ( void )
{ //body
char string[] = "readLine";
char * encryptedString = readLine_str_test_encrypt( string, strlen(string) );
// Note: the encrypted string may not be printable
printf("%s\n", encryptedString );
char * decryptedString = readLine_str_test_decrypt( encryptedString, strlen(string) );
printf( "%s\n", decryptedString );
free( encryptedString );
free( decryptedString );
} // end function: main
char* readLine_str_test_decrypt( char *encryptedString, size_t length)
{
char *string = NULL;
if( NULL == ( string = malloc( length +1) ) )
{// then malloc failed
perror( "malloc for decrypted string failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
for ( size_t i=0; encryptedString[i]; ++i )
{
string[i] = encryptedString[i] ^22;
}
string[length] = '\0';
return string;
} // end function: readLine_str_test_decrypt
char* readLine_str_test_encrypt( char *stringToEncrypt, size_t length )
{
char *output = NULL;
if( NULL == (output = malloc( length+1 ) ) )
{ // then, malloc failed
perror( "malloc for work area failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
for( size_t i=0; stringToEncrypt[i]; ++i)
{
output[i] = stringToEncrypt[i] ^22;
}
output[length] = '\0';
return output;
} // end function: readLine_str_test_encrypt
the output from the above code is:
dswrZxs
readLine
so I'm trying to create a program which looks at a string defined in main, and deletes any non-alphabetical characters (excluding \0). So far this is my code:
/* Write code to which considers the string currently saved
* in the 'name' array, removes all spaces and non-alphabetical
* chars from the string, and makes all alphabetical characters
* lower case. */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define NAMELEN 30
int main (void) {
char name[NAMELEN];
strcpy(name, " William B. Gates");
int i, length, check;
length = strlen(name);
for ( i = 0; i < length; i++ ) {
check = isalpha(name[i]);
if ( check == 0 ) {
for ( ; i < length; i++ ) {
name[i] = name[i+1];
}
}
}
printf("The length is %lu.\n", strlen(name));
printf("Name after compression: %s\n", name);
return EXIT_SUCCESS;
}
So for the test data, " William B. Gates", the output should be "WilliamBGates", unfortunately the output I'm getting is:
The length is 16.
Name after compression: William B. Gates
I think the space before William has been deleted, but I'm unable to tell.
Thanks for any help!
You don't need a complicated double-loop for this at all. The purpose of the exercise is to maintain independent source-reader and destination-writer, only copying and advancing the latter when the former is qualified by your criteria (i.e. it answers true to isalpha).
in other words:
#include <stdio.h>
#include <ctype.h>
int main (void)
{
char name[] = " William B. Gates";
char *dst = name, *src;
for (src = name; *src; ++src)
{
if (isalpha((unsigned char)*src))
*dst++ = *src;
}
*dst = 0; // terminate the string
printf("result: %s\n", name);
}
Output
result: WilliamBGates
I leave translating to lower case during the copy-step as an exercise for you. (from your in-code comment: "makes all alphabetical characters lower case").
This inner loop is wrong
if ( check == 0 ) {
for ( ; i < length; i++ ) {
name[i] = name[i+1];
}
It copies the string in itself excluding the first character and after that your program does nothing because i is already equal to length.
So the program only removes one non-alpha character from the string.
When you are going to traverse a string sequantially then there is no need to calculate its length. The program can be written simpler or at least you may use the approach that is demonstrated below. For example
#include <stdio.h>
#include <ctype.h>
int main( void )
{
char name[] = " William B. Gates";
printf( "\"%s\"\n", name );
size_t j = 0;
for ( size_t i = 0; name[i] != '\0'; i++ )
{
if ( isalpha( ( unsigned char )name[i] ) )
{
if ( j != i ) name[j] = name[i];
++j;
}
}
name[j] = '\0';
printf( "\"%s\"\n", name );
}
The program output is
" William B. Gates"
"WilliamBGates"
The posted code tries to hard.
The following code
compiles cleanly
contains useful comments to clarify what is being done
performs correctly
uses meaningful variable names
notice the simplicity of the code, and all performed in only one pass through the name[] array.
#include <stdio.h>
#include <ctype.h>
int main( void )
{
char name[] = " William B. Gates";
printf( "\"%s\"\n", name );
size_t src = 0;
size_t dest = 0;
for( ; name[src]; src++) // will exit loop when string terminator '\0' encountered
{
if( isalpha(name[src]) )
{ // then current char is: a...zA...Z
name[dest] = tolower(name[src]); // force lower case
dest++; // update where to save next character
}
}
name[dest] = '\0'; // terminate the modified string
printf( "\"%s\"\n", name );
return 0;
} // end function: main
#include <stdio.h>
#include <ctype.h>
int isPalindrome( char *str, int length )
{
if ( length < 1 )
{
return 1; /* no more chars to compare, its a palindrome */
}
if ( str[0] == str[length-1] ) /* Are the two ends same? */
{
return isPalindrome( str+1, length-2 ); /* continue checking */
}
else
{
return 0; /* comparison failed, not a palindrome */
}
}
void strToUpper( char *src )
{
/* convet to upper case any letter */
while( ( *src = toupper( *src ) ) != '\0' )
{
++src;
}
}
int main( void )
{
int result = 0;
char str[40] = { '\0' };
printf( "Please type the string to identify Palindrom or not: ", stdout );
fflush( stdout );
fgets( str, sizeof str, stdin );
strToUpper( str ); /* make all letters the same for comparison */
result = isPalindrome( str, ( strlen( str ) - 1 ) ); /* recursive starts here */
if( result == 1 )
{
printf( "1" );
}
else
{
printf( "0" );
}
getchar();
return 0;
}
I wrote this code which identifies palidromes in C, but I want to use scanf instead of fputs or fgets, so I can understand the other way to solve this problem.
There is no fputs and only a single call to fgets in this code.
The method of input here really don't affect "way to solve this problem". It's the same code - changing one line won't change lot. scanf not a safe function. You can do scanf("%s", str) but fgets is better and recommended. If you need to analyze string after fgets, you can use sscanf.