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
Related
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<cstdlib>
#define MAX_SIZE 1024
int line_count = 0;
void readFile(FILE *fptr, int *line);
int main(void) {
FILE *fptr;
readFile(fptr, &line_count);
return 0;
}
void readFile(FILE *fptr, int *line) {
fptr = fopen("C:\\Users\\xxx\\Desktop\\english_words.txt", "r");
char wordList[MAX_SIZE];
char *englishWords[MAX_SIZE];
while(fgets(wordList, MAX_SIZE, fptr) != NULL){
char *token = strtok(wordList, "=");
englishWords[*line] = token;
*line += 1;
}
for(int i = 0; i < line_count; i++){
//printf("%s",englishWords[i]);
}
}
I need to insert the data in the token variable one by one into the englishWords array
for example:
englishWords[0] = redudancy
englishWords[1] = overlap
While doing this, I noticed a problem while debugging. The address of the token variable I put in EnglishWords never changes, so I guess all indexes are filled with the last word of the text file.
a screenshot from the debug moment
In the line
englishWords[*line] = token;
you are making englishWords[*line] point inside the array wordList. However, in the next loop iteration, you overwrite the content of wordList. Therefore, you are probably also overwriting what the pointer from the previous loop iteration is pointing to. This is not what you want.
Therefore, you should instead make a copy of the token, which will not be overwritten, and make englishWords[*line] point to that copy.
In order to make a copy of a string, you can use malloc to allocate memory for the copy of the string, and then use strcpy to actually copy it. Some platforms provide the function strdup which combines both of these function calls in one function call.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_SIZE 1024
int line_count = 0;
void readFile(FILE *fptr, int *line);
int main(void) {
FILE *fptr;
readFile(fptr, &line_count);
return 0;
}
void readFile(FILE *fptr, int *line) {
fptr = fopen("C:\\Users\\xxx\\Desktop\\english_words.txt", "r");
char wordList[MAX_SIZE];
char *englishWords[MAX_SIZE];
while(fgets(wordList, MAX_SIZE, fptr) != NULL){
char *token = strtok(wordList, "=");
//allocate memory for the copy of the string
englishWords[*line] = malloc( strlen(token) + 1 );
if ( englishWords[*line] == NULL )
{
fprintf( stderr, "Memory allocation error!\n" );
exit( EXIT_FAILURE );
}
//actually copy the string
strcpy( englishWords[*line], token );
*line += 1;
}
for(int i = 0; i < line_count; i++){
//printf("%s",englishWords[i]);
}
//cleanup
//free allocated memory
for ( int i = 0; i < *line; i++ )
{
free( englishWords[i] );
}
//close the file
fclose( fptr );
}
I', learning C and I'm getting no output for some reason, probably I don't return as I should but how I should? (described the problem in the comments below :D)
Any help is appreciated!
#include <stdio.h>
#include <ctype.h>
#include <string.h>
char *makeUpperCase (char *string);
int main()
{
printf(makeUpperCase("hello")); //Here there is no output, and when I'm trying with the format %s it returns null
return 0;
}
char *makeUpperCase(char *string)
{
char str_out[strlen(string) + 1];
for (int i = 0; i < strlen(string); ++i)
str_out[i] = toupper(string[i]);
printf(str_out); //Here I get the output.
return str_out;
}
You declared within the function a local variable length array that will not be alive after exiting the function
char str_out[strlen(string) + 1];
So your program has undefined behavior.
If the function parameter declared without the qualifier const then it means that the function changes the passed string in place. Such a function can be defined the following way
char * makeUpperCase( char *string )
{
for ( char *p = string; *p != '\0'; ++p )
{
*p = toupper( ( unsigned char )*p );
}
return string;
}
Otherwise you need to allocate dynamically a new string. For example
char * makeUpperCase( const char *string )
{
char *str_out = malloc( strlen( string ) + 1 );
if ( str_out != NULL )
{
char *p = str_out;
for ( ; *string != '\0'; ++string )
{
*p++ = toupper( ( unsigned char )*string );
}
*p = '\0';
}
return str_out;
}
Here is a demonstration program.
#include <stdop.h>
#include <stdlib.h>
#include <string.h>
char *makeUpperCase( const char *string )
{
char *str_out = malloc( strlen( string ) + 1 );
if (str_out != NULL)
{
char *p = str_out;
for (; *string != '\0'; ++string)
{
*p++ = toupper( ( unsigned char )*string );
}
*p = '\0';
}
return str_out;
}
int main( void )
{
char *p = makeUpperCase( "hello" );
puts( p );
free( p );
}
The program output is
HELLO
The problem is that printf() is buffering output based on a bit complex mechanism. When you are outputting to a terminal, printf() just buffers everything until the buffer fills (which is not going to happen with just the string "hello", or until it receives a '\n' character (which you have not used in your statement)
So, to force a buffer flush, just add the following statement
fflush(stdout);
after your printf() call.
#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 access a const char* created in function1 in function2 in order to use it for some operations. It has to be in a different function for several reasons.
I've tried using this code in function2:
const char* str[1024] = { function1() };
but I had no success whatsoever. If I try
printf("%s\n", str[1]);
in function2, it just prints (null).
I've also tried using malloc, but I had no success.
//main function {it does its thing, it wouldn't interest us}
//function1 {it creates a const char* var[1024];)
//function2 {here I want to use the const char* var[1024]; from function1}
Observation: In function1, the const char* prints just fine what it needs to print.
I wish I could find a way to solve this. Thank you for your patience!
Later edit for code:
const char* function1()
{
lang = fopen("lang.csv", "r");
int i = 0;
char line[1024];
const char* word[1024];
char num[] = { 1 , 2 };
while (fgets(line, 1024, lang))
{
char* tmp = _strdup(line);
printf("Field 1 would be %s\n", getfield(tmp, num[0])); // NOTE strtok clobbers tmp
word[i] = getfield(tmp, num[0]);
i++;
free(tmp);
}
printf("%s\n", word[1]); //prints successfully
fclose(lang);
return NULL;
}
int function2() {
const char* word[1024] = { function1() };
printf("%s\n", word[1]); // failure, prints (null)
}
You have a number of problems.
word is not static so does not exist outside of function1()
Even if word were static, its elements point to content in tmp which is free()'d before function1() returns.
function1() returns NULL - presumably the intent was to return the pointer word? But that would be incorrect in any event for all the reasons above.
function2() assigns as many word pointers as there are lines in the file, which may be more than the allocated 1024.
This problem can be solved in a number of ways. One way is to pass the array of pointers to words to function1() and have function1() allocate space for each word. This then requires function2() to take responsibility for freeing the allocated words when done. Not a method I'd normally recommend, but the alternative is to define some arbitrary fixed maximum length for each word.
I have made some assumptions about the semantics of getfield() and removed the array num as it seems to serve no purpose in the original code.
int function1( const char** words, size_t max_words )
{
FILE* lang = fopen( "lang.csv", "r" );
char line[1024];
size_t i = 0;
while( i < max_words && fgets( line, 1024, lang ) != NULL )
{
printf( "Field 1 would be %s\n", getfield( line, 1 ) ) ;
const char* tmp = getfield( line, 1 );
char* word = malloc( strlen( tmp) + 1 ) ;
strcpy( word, tmp ) ;
i++ ;
}
printf( "%s\n", words[1] ); //prints successfully
fclose( lang );
return i ;
}
int function2()
{
char* word[1024] = {0} ;
// Fill the word list
int count = function1( word, sizeof(word) / sizeof(*word) ) ;
// Print first word
printf( "%s\n", word[1] ); //failure, prints (null)
// Delete list elements allocated by function2()
for( int i = 0; i < count; i++ )
{
free( word[i] ) ;
}
return count ;
}
This is a stand-alone example that shows you how to allocate your word list from the heap and return it to another function:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_COUNT 1024
const char **function1(void) {
const char **word = malloc(sizeof(const char *) * WORD_COUNT);
for (int index = 0; index < WORD_COUNT; index++) {
// You would replace these lines with your getfield code
char number[20];
snprintf(number, sizeof(number), "%d", index);
word[index] = strdup(number);
}
// We return word here because that is how we pass the result to the caller
return word;
}
void function2(void) {
const char **word = function1();
printf("word[1] = %s\n", word[1]);
}
int main(void) {
function2();
return 0;
}
Output
word[1] = 1
Warning
The program allocates memory via malloc and strdup but does not call free to de-allocate it. This could result in memory leaks.
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 );
}
}