Testing length of inputed message with old message - c

I'm working on a program that asks me to enter a new message and replacing the old one, but I have to test if the message is longer than the last one. I would like to get answer that is similar to my program because this is a lesson I'm learning right now. It asks me to input size of new char, but when I test it, it takes my set size for testing.
#include <stdio.h>
#include <stdlib.h>
void editedMessage(char* nmessage, int size){
char newMessage[];
printf("Enter a new message!\n");
gets_s(newMessage, sizeof(newMessage));
if (size > sizeof(newMessage)){
for (int i = 0; i < sizeof(newMessage); i++){
nmessage[i] = newMessage[i];
}
}
else {
printf("New message is too long.\n\n");
}
}
void main(){
char message[] = "This is some message!";
printf("Old message\n%s\n\n", message);
editedMessage(message, sizeof(message));
printf("New message\n\n%s\n\n", message);
}
EDIT: I edited next code but now says 'stack around the variable 'message' was corrupted'
char newMessage[256];
printf("Enter a new message!\n");
gets_s(newMessage, sizeof(newMessage));
int len = strlen(newMessage);
if (size > len){
for (int i = 0; i < sizeof(newMessage); i++){
nmessage[i] = newMessage[i];
}
}

I changed the return type of editedMessage to char* and cut down it arguments.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LENGTH 1000
char* editedMessage(char* oldMessage){
char newMessage[MAX_LENGTH];
printf("Enter a new message : ");
fgets(newMessage,MAX_LENGTH,stdin);
if (strlen(newMessage)<= strlen(oldMessage)){
strcpy(oldMessage,newMessage);
}
else {
printf("New message is too long.\n\n");
}
return oldMessage; // In fact the value of oldMessage should have been changed if the new message is shorter in length
}
void main(){
char message[MAX_LENGTH] = "This is some message!";
printf("Old message : %s\n", message);
editedMessage(message);
/* Since we are dealing with pointers, note that I am not catching any
* return values here. In essence any changes made to message in the
* editedMessage function is automatically effective in the main
* function.
*/
printf("New message :%s\n", message);
}

Related

String in structure gets deleted

I'm working on the last exercise of the "Think like a computer scientist, C version" book and I have some trouble with one particular point.
The exercise consists of making a small game, where the computer picks a random value between 0 and 20 and then asks me to guess the number.
After that, the computer counts the number of tries I made and, if I get a better score than the previous party, I need to store my name and the number of tries in a structure.
My problem is the following: When I restart the game, the string value, player_name, in the structure gets somehow deleted but player_score is still there.
First, I made a "call by value" function to create the structure and then a tried with a "call by reference" but getting the same results.
I think I tried everything I could with my actual knowledge for now; so, if someone could check my code and give me some tips about what's wrong I would much appreciate it!
//HEADERS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define FALSE 0
#define TRUE 1
//TYPEDEF STRUCTS
typedef struct
{
int player_score;
char *player_name;
} HS_Player;
//FUNCTION PROTOTYPES
int Random_Value(void);
int Get_User_Choice(void);
int Check_Result(int computer, int my_choice);
int Try_Again(int game_result, int computer);
void Player_Infos(HS_Player *player_p, int score);
int Game_Restart(void);
//MAIN
int main(void)
{
int end_game;
int high_score_value = 100;
HS_Player player;
while (end_game != TRUE)
{
int computer_number = Random_Value();
printf("Guess the number between 0 et 20 chosen by the computer.\n");
int your_number = Get_User_Choice();
int result_game = Check_Result(computer_number, your_number);
int tries_to_win = Try_Again(result_game, computer_number);
printf("Number of tries: %i\n", tries_to_win);
if (tries_to_win < high_score_value)
{
Player_Infos(&player, tries_to_win );
high_score_value = player.player_score;
}
printf("Highest score: %i By: %s\n", player.player_score, player.player_name);
printf("\n");
end_game = Game_Restart();
}
return EXIT_SUCCESS;
}
//Random_Value FUNCTION
int Random_Value(void)
{
srand(time(NULL));
int x = rand();
int y = x % 20;
return y;
}
//Get_User_Choice FUNCTION
int Get_User_Choice(void)
{
int success, x;
char ch;
printf("Your Guess:\t");
success = scanf("%i", &x);
while (success != 1)
{
printf("Your input is not a number. Please try again:\t");
while ((ch = getchar()) != '\n' && ch != EOF);
success = scanf("%i", &x);
}
if (x < 0 || x > 20)
{
printf("Your input must be between 0 and 20. Please try again.\n");
Get_User_Choice();
}
return x;
}
//Check_Result FUNCTION
int Check_Result(int computer, int my_choice)
{
int check_result;
if (my_choice < computer)
{
printf("Computer number is larger!\n");
check_result = FALSE;
}
else if (my_choice > computer)
{
printf("Computer number is smaller!\n");
check_result = FALSE;
}
else if (my_choice == computer)
{
printf("It's a Match! You chose the same number than the computer.\n");
printf("\n");
check_result = TRUE;
}
return check_result;
}
//Try_Again FUNCTION
int Try_Again(int game_result, int computer)
{
int tries_befor_success = 1;
while (game_result != TRUE)
{
int your_number = Get_User_Choice();
game_result = Check_Result(computer, your_number);
tries_befor_success++;
}
return tries_befor_success;
}
//Player_Infos FUNCTION
void Player_Infos(HS_Player *player_p, int score)
{
char new_name[80];
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
scanf("%s", new_name);
printf("\n");
player_p->player_score = score;
player_p->player_name = new_name;
}
//Game_Restart FUNCTION
int Game_Restart(void)
{
int quit_value;
printf("Quit Game ?\n");
printf("Press 'y' to quit or any other keys to continue.\n");
fflush(stdin);
char quit_game = getchar();
printf("\n");
if (quit_game == 'y')
{
quit_value = TRUE;
}
else
{
quit_value = FALSE;
}
return quit_value;
}
The problem is that, in your Player_Infos function, you are assigning the address of a local array to the char* player_name pointer member of the passed structure. When that function ends, the local array it used will be deleted and the pointer in the structure will be invalid. (In the case of the player_score, you don't have that problem, because the given value is copied to the structure member.)
There are several ways around this; one would be to use the strdup() function to make a copy of the local char new_name[80]; array – but that is really overkill, and you would need to manage (i.e. free()) that allocated string whenever you make a modification.
A simpler way is to make the player_name member an actual array of char and then use strcpy() to copy the local array into that member.
Better, still, with the player_name member defined as char [80], you can read directly into that (in the function), and avoid the local array completely:
typedef struct
{
int player_score;
char player_name[80];
} HS_Player;
//...
void Player_Infos(HS_Player *player_p, int score)
{
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
// Read directly. Limit input to 79 chars (allowing room for null terminator).
scanf("%79s", player_p->player_name);
printf("\n");
player_p->player_score = score;
}
Also, just as a "style" tip, you may want to change the member names to just score and name, as the "player" part is implied by the structure type-name itself.
This issue you are having is that you are associating the player name pointer to a variable that goes out of scope when you leave the "player_Infos" function. What you probably would want to do is define the name as a character array in your structure and then use the "strcpy" call in your function instead. Following is a couple of code snippets illustrating that point.
//TYPEDEF STRUCTS
typedef struct
{
int player_score;
char player_name[80];
} HS_Player;
Then, in your function, use the "strcpy" call.
//Player_Infos FUNCTION
void Player_Infos(HS_Player *player_p, int score)
{
char new_name[80];
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
scanf("%s", new_name);
printf("\n");
player_p->player_score = score;
strcpy(player_p->player_name, new_name);
//player_p->player_name = new_name;
}
When I tested that out, I got a name to appear in the terminal output.
Computer number is smaller!
Your Guess: 4
It's a Match! You chose the same number than the computer.
Number of tries: 8
Highest score: 4 By: Craig
FYI, you will need to include the "string.h" file.
Give that a try.
Name Update
The reason your player.player_name is not getting updated is because you can't assign a string this way in C. When doing player_p->player_name = new_name; you're actually saving in player_p->player_name the memory address of new_name.
Instead, what you want to achieve, is to copy each character of new_name to player_p->player_name and in order to achieve this, you have to change the type of prlayer_name field from char* player_name to char player_name[80], then assign it using, for example, strcpy():
#include <string.h>
// [...]
//TYPEDEF STRUCTS
typedef struct
{
unsigned int player_score;
char player_name[80];
} HS_Player;
// [...]
//Player_Infos FUNCTION
void Player_Infos(HS_Player *player_p, int score)
{
char new_name[80];
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
scanf("%s", new_name);
printf("\n");
player_p->player_score = score;
strcpy(player_p->player_name, new_name);
}
Data Persistence
To make data (players info) persistent over multiple runs, you have to save the content of the struct to a file.
Example
int Save_Score(char* filename, HS_Player* player)
{
FILE* file = fopen(filename, "w");
if (file == NULL)
{
fprintf(stderr, "\nAn error occurred while opening the file\n");
return -1;
}
if (fprintf(file, "%d %s", player->player_score, player->player_name) < 0)
return -1;
fclose(file);
return 0;
}
int Load_Score(char* filename, HS_Player* player)
{
FILE* file = fopen(filename, "r");
if (file == NULL)
{
fprintf(stderr, "\nAn error occurred while opening the file\n");
return -1;
}
if (fscanf(file, "%d %79s", &player->player_score, player->player_name) < 0)
return -1;
fclose(file);
return 0;
}

C: variables retain the value from previous operation instead of resetting

I am fairly new to C and have been trying my hand with some arduino projects on Proteus. I recently tried implementing a keypad and LCD interface with Peter Fleury's libraries, so far the characters I input are displayed fine, but I run into a problem when trying to print to the serial port. It's like the value of the keys keeps on being concatenated with every iteration so the ouput has extra characters like this:
The value before the comma is from the 'key' variable, the value after it the 'buf' variable:
151
(The 5 I input in the second iteration was added to the 1 from the first iteration and then put into the variable I print)
I figure it may be due to my lack/incorrect use of pointers, heres is my code:
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
#include "lcd.h"
#include "mat_kbrd.h"
#include "funciones.h"
#include "menu.h"
char buf[256];
char* coma = ",";
int main(void)
{
pin_init();
serial_begin();
lcd_init(LCD_DISP_ON);
kbrd_init();
bienvenida();
while (1) {
int i = 0;
char key = 0;
//char *peso;
//int pesoSize = 1;
char peso[100];
//peso = calloc(pesoSize,sizeof(char));
int salida = 0;
lcd_clrscr();
desechos();
key = kbrd_read();
if (key != 0) {
lcd_gotoxy(0,3);
lcd_putc(key);
_delay_ms(2000);
lcd_clrscr();
cantidad();
while (salida != 1) {
char keypeso = 0;
keypeso = kbrd_read();
//pesoSize = i;
//peso = realloc(peso,pesoSize*sizeof(char));
if (keypeso != 0) {
if (keypeso == '+') {
salida = 1;
keypeso = *("");
lcd_clrscr();
calcularTotal(key,peso);
_delay_ms(2000);
} else {
lcd_gotoxy(i,1);
lcd_putc(keypeso);
snprintf(peso, sizeof peso, "%s%s",peso, &keypeso);
//strcat(peso,&keypeso);
i++;
_delay_ms(2000);
}
}
}
snprintf(buf, sizeof buf, "%s%s%s", &key,coma,peso);
serial_println_str(buf);
}
}
}
&key and &keypeso point to a single char, but you are using the %s format specifier, so trying to read a string into a single char. Use %c rather then %s for single characters, and pass the char not the address-of-char..

Python's binascii.unhexlify function in C

I'm building a program that takes input as if it is a bare MAC address and turn it into a binary string. I'm doing this on a embedded system so there is no STD. I have been trying something similar to this question but after 2 days I haven't achieved anything, I'm really bad with these kind of things.
What I wanted is output to be equal to goal, take this into consideration:
#include <stdio.h>
int main() {
const char* goal = "\xaa\xbb\xcc\xdd\xee\xff";
printf("Goal: %s\n", goal);
char* input = "aabbccddeeff";
printf("Input: %s\n", input);
char* output = NULL;
// Magic code here
if (output == goal) {
printf("Did work! Yay!");
} else {
printf("Did not work, keep trying");
}
}
Thanks, this is for a personal project and I really want to finish it
First, your comparison should use strcmp else it'll be always wrong.
Then, I would read the string 2-char by 2-char and convert each "digit" to its value (0-15), then compose the result with shifting
#include <stdio.h>
#include <string.h>
// helper function to convert a char 0-9 or a-f to its decimal value (0-16)
// if something else is passed returns 0...
int a2v(char c)
{
if ((c>='0')&&(c<='9'))
{
return c-'0';
}
if ((c>='a')&&(c<='f'))
{
return c-'a'+10;
}
else return 0;
}
int main() {
const char* goal = "\xaa\xbb\xcc\xdd\xee\xff";
printf("Goal: %s\n", goal);
const char* input = "aabbccddeeff";
int i;
char output[strlen(input)/2 + 1];
char *ptr = output;
for (i=0;i<strlen(input);i+=2)
{
*ptr++ = (a2v(input[i])<<4) + a2v(input[i]);
}
*ptr = '\0';
printf("Goal: %s\n", output);
if (strcmp(output,goal)==0) {
printf("Did work! Yay!");
} else {
printf("Did not work, keep trying");
}
}

Unix - Writing a line from a file to a char* var, then saving it in integers

Question: I have a file, called ATM1, and it is filled with strings, for example(this is the format for everyline): O ilan 123 456 Which means - O stands for open account, ilan is username, 123 is password, and 456 is initial amount in my bank account.
After opening the file, iterating with a while loop while(((ret_in = read (in1, &buffer1, BUF_SIZE)) > 0)), I want to get the line's details and store them in the appropriate variables. for example the first char will be stored in a variable called letter or msg[0] whatever is more convenient for you, then there is a space and then username, then password, and optional stuff like balance, or maybe another account id (for transfer money purposes).
Every ATM machine should be a thread, it has its own file, for now it is just one file "ATM1" because I want it to work in the beginning for at least one file.
Current Problem:
Segmentation fault in the OpenFile function. I'm still not able to store the line's values in the appropriate variables and called the switch statement for opening account, etc.
Here is the current code:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#define BUF_SIZE 8192
sem_t log;
void OpenNewAccount(int acc,int pw,int amount){
}
struct Account{
int number;
int password;
int balance;
};
//*Opens file for every ATM
void* openFile(void* args){
//To add later: while(true) { sleep(100); do next file's line }
//Open file
int* aargs = args;
int acc;
int pw;
int amount;
int target_acc;
int ret_in, in1,file;
char buffer1[BUF_SIZE];
int count = 0;
int i = 0;
char fn[5] = "ATM1";
char* msg;
file = open(fn,O_RDONLY|O_CREAT,0644);
while(((ret_in = read (file, &buffer1, BUF_SIZE)) > 0))
{
for(i; i<ret_in; i++)
{
if(buffer1[i]!='\n')
msg[i] = buffer1[i];
/* else{
if(count == 0){
count++;
break;
}
else
{
count = i + 1;
break;
}
}
*/
}
}
printf("%s", msg); //TEST: check msg
//Here we translate the message
/*
//Here we call the relevant function of the msg
switch (msg[count - 1]){
case 'O': OpenNewAccount(acc,pw,amount);
case 'D': Deposit(acc,pw,amount);
case 'W': Withdrawl(acc,pw,amount);
case 'B': Balance(acc,pw);
case 'Q': CloseAccount(acc,pw);
case 'T': Transfer(acc,pw,target_acc,amount);
}
*/
}
//*finish: Update log.txt and lock it
void WriteLog(char* msg){
int file;
char logName[8] = "log.txt";
sem_wait(&log);
file = open(logName,O_WRONLY|O_CREAT,0644);
strcat(msg,"\n");
write(file,&msg,strlen(msg));
close(file);
sem_post(&log);
}
int main(void)
{
int i,n,a;
sem_init(&log, 0, 1);
printf("Please enter the number of ATMs you want: \n");
scanf("%d", &n);
int bank; //bank with n ATMs
pthread_t thread[3];
printf("test\n"); //TEST: check msg
for(i = 0; i < 3; i++)
pthread_create ( &thread[i] , NULL , openFile , &i);
scanf("%d",&a);
}
Well, for one, you use i as an array index without ever initializing it. That could easily cause a SEGFAULT.
But honestly this whole thing is a mess. Your function names don't do what they say they do. You appear to be thrashing around almost randomly. I suggest you rethink your design from the beginning. Go through the "top down" design process you should have learned and figure out how to factor your code. Only then should you proceed.

Getting the error "undefined reference to". Can you explain what it means and where I have made the mistake?

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <string.h>
#include <signal.h>
#include <pwd.h>
#include <sys/types.h>
#include <crypt.h>
#include "pwent.h"
#define TRUE 1
#define FALSE 0
#define LENGTH 16
void sighandler() {
signal(SIGINT,SIG_IGN);
}
int main(int argc, char *argv[]) {
mypwent *passwddata;
/* see pwent.h */
char important[LENGTH] = "***IMPORTANT***";
char user[LENGTH];
char prompt[] = "password: ";
char swap_prompt[]="New password: ";
char again_prompt[]="Again: ";
char *user_pass;
char *new_pass;
char *again_pass;
int f_login;
char *en_pass;
char *envp[] = { NULL };
char *argvv[] = { "/bin/sh",NULL};
sighandler();
while (TRUE) {
/* check what important variable contains - do not remove, part of buffer overflow test */
printf("Value of variable 'important' before input of login name: %s\n",
important);
printf("login: ");
fflush(NULL); /* Flush all output buffers */
__fpurge(stdin); /* Purge any data in stdin buffer */
if (fgets(user,16,stdin) == NULL) /* gets() is vulnerable to buffer */
{
exit(0); /* overflow attacks. */
}
*/* check to see if important variable is intact after input of login name - do not remove */*
printf("Value of variable 'important' after input of login name: %*.*s\n",
LENGTH - 1, LENGTH - 1, important);
user_pass = getpass(prompt);
passwddata = mygetpwnam(user);
if (passwddata != NULL) {
en_pass=crypt(user_pass,passwddata->passwd_salt);
if (!strcmp(en_pass, passwddata->passwd)) {
if(passwddata->pwage==10){
printf("You need to swap your password!!! \n");
do{
new_pass=getpass(swap_prompt);
again_pass=getpass(again_prompt);
}while(strcmp(new_pass,again_pass));
printf("Password changed!!! \n");
passwddata->passwd=new_pass;
passwddata->pwage=0;
}else{
printf(" You're in !\n");
printf("Number of failed login is %d\n", passwddata->pwfailed);
passwddata->pwfailed=0;
passwddata->pwage++;
}
mysetpwent(user,passwddata);
setuid(passwddata->uid);
execve("/bin/sh",argvv,envp);
}else{
if(passwddata->pwfailed==3){
printf("You attempted too many times \n");
passwddata->pwfailed=0;
mysetpwent(user,passwddata);
return 0;
}
printf("Wrong password, please try again!!! \n");
f_login++;
passwddata->pwfailed=f_login;
mysetpwent(user,passwddata);
}
}else{
printf("Login Incorrect \n");
}
}
return 0;
}
So I get the error "undefined reference to mygetpwnam" and "undefined reference to mysetpwent". I am not sure what this exactly means and how to go about correcting it. This is a part of an assignment I am working on with regards to unix and their password systems.
You attempt to call the function mygetpwnam once in your code, and mysetpwent three times, yet those functions are not defined anywhere. Hence, you reference something undefined, an error.
"mygetpwnam" and "mysetpwent" are defined in pwd.h. Open and check if pwd.h has definition for "mygetpwnam" and "mysetpwent".
Check pwent.h to see if your functions are declared there (definition should be in pwent.c). Also make sure you haven't misspelled the function names. You should show us how you compile the program.

Resources