Function to decrypt file in C? - c

I have a file with a large number of 'prospects', so each line has an encrypted last name, an encrypted first name, a 12 digit id code, and then 4 ratings (3 ints, 1 float). Encryption is shifting every character of the names by the value of the last number in the file (found to be 310).
Attempted to create a function to decrypt 1 character, then another function to decrypt a string (name) using this function, but am getting errors and segmentation faults, please help!
#include <stdio.h>
#include <stdlib.h>
#define MSTRLEN 20
#define MAX_SIZE 1000
/* structure prototype */
typedef struct {
char lastname[MSTRLEN];
char firstname[MSTRLEN];
char secretcode[13];
int rank1;
int rank2;
float rank3;
int rank4;
} prospect_t;
int main (void)
{
FILE *ifile;
prospect_t *prospects;
char last[MSTRLEN],first[MSTRLEN],code[13],last_name,first_name;
int r1,r2,r4,num_prospects,shift,i,j;
float r3;
char unencrypt_letter(char *letter, int shift);
char unencrypt_name(char name[MSTRLEN], int shift);
/*finding how many prospects and last integer*/
ifile = fopen("prospects.txt","r");
num_prospects = 0;
if (ifile == NULL){
printf("File not found!\n");
return (-1);
}
while (fscanf(ifile,"%s %s %s %d %d %f %d",last,first,code,&r1,&r2,&r3,&r4)!=EOF){
num_prospects++;
}
shift = r4%26;
fclose(ifile);
/*--------------------------------------*/
/* dynamic memory allocation */
prospects = (prospect_t*)malloc(num_prospects*sizeof(prospect_t));
ifile = fopen("prospects.txt","r");
if (ifile == NULL){
printf("File not found!\n");
return (-1);
}
for(i=0;i<num_prospects;i++){
fscanf(ifile,"%s %s %s %d %d %f %d", prospects[i].lastname,prospects[i].firstname,prospects[i].secretcode,&prospects[i].rank1,&prospects[i].rank2,&prospects[i].rank3,&prospects[i].rank4);
}
/* to be used once get working
for(j=0;j<num_prospects;j++){
prospects[j].lastname = unencrypt_name(prospects[j].lastname,shift);
prospects[j].firstname = unencrypt_name(prospects[j].firstname,shift);
}
*/
/* to be taken out once working */
last_name = unencrypt_name(prospects[0].lastname,shift);
first_name = unencrypt_name(prospects[0].firstname,shift);
printf("%s %s\n",last_name,first_name);
fclose(ifile);
free(prospects);
return(0);
}
/* function to unencrypt one letter */
char unencrypt_letter(char *letter, int shift)
{
char *new_letter;
if ((*letter - shift) < 'a')
*new_letter = (char)((*letter - shift) + 26);
else
*new_letter = (char)(*letter - shift);
return(*new_letter);
}
/* function to unencrypt a name */
char unencrypt_name(char name[MSTRLEN],int shift)
{
char new_name[MSTRLEN];
int k;
k = 0;
while (name[k] != '\0'){
new_name[k] = unencrypt_letter(name[k],shift);
k++;
}
return(*new_name);
}
From terminal, I am getting the following:
la2.c: In function ‘main’:
la2.c:68:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
la2.c:68:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat]
la2.c: In function ‘unencrypt_name’:
la2.c:99:3: warning: passing argument 1 of ‘unencrypt_letter’ makes pointer from integer without a cast [enabled by default]
la2.c:79:6: note: expected ‘char *’ but argument is of type ‘char’
** Link phase
gcc -o la2 la2.o
Compile and link completed successfully
Your binary can be run by typing:
la2
engs20-1:~/engs20/workspace$ la2
Segmentation fault

Read the warnings again, they are quite clear:
la2.c:68:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’
It tells you that the second argument to the printf call on line 68 is expected to be a string (char *) but you pass an integer (actually a single char, but the compiler casts it to int) as that argument instead.
Later when you run the program printf uses that integer as a pointer to a string, and as that integer is not a proper integer the program crashes.

Assuming the 2nd fscanf is line 68
fscanf(ifile,"%s %s %s %d %d %f %d", prospects[i].lastname,prospects[i].firstname,prospects[i].secretcode,&prospects[i].rank1,&prospects[i].rank2,&prospects[i].rank3,&prospects[i].rank4);
I'd stick some () in to make sure you are getting the address of what you think.
&(prospects[i].lastname), ...
You don't pre declare char unencrypt_letter(char *letter, int shift) before you call it, so the compiler assumes it returns an int.
Add a predeclaration of it before main().

Related

Why isn't my code producing a random sequence of numbers between 1 and N? No file is produced. What is the error in my code? What am I doing wrong?

The goal of the program is to generate a random sequence of numbers between 1 and N, where N is passed as an argument to the program, and write the resulting sequence to a file.
My file isn't produced. What am I doing wrong? Are there any errors in my code? Is there something wrong with my code? Am I outputting the file correctly?
/*01*/ //
/*02*/ // random_sequence_v6.c
/*03*/ // Generate a random sequence of all numbers between 1 to N
/*04*/ //
/*05*/ #include "stdio.h"
/*06*/ #include "stdint.h"
/*07*/ #include "stdlib.h"
/*08*/ #include "stdint.h"
/*09*/ #include "sys/types.h"
/*10*/ #include "sys/stat.h"
/*11*/ #include "fcntl.h"
/*12*/ #include "assert.h"
/*13*/ #include "inttypes.h"
/*14*/
/*15*/ typedef uint64_t value_t;
/*16*/
/*17*/ value_t* generate_sequence(int num_values)
/*18*/ {
/*19*/ assert(num_values > 0);
/*20*/ value_t* data = calloc(num_values, sizeof(int));
/*21*/ for (int i = 0; i <= num_values; i++) {
/*22*/ data[i] = i;
/*23*/ }
/*24*/ return data;
/*25*/ }
/*26*/
/*27*/ int random_value(int min, int max)
/*28*/ {
/*29*/ int random_number;
/*30*/ do {
/*31*/ random_number = rand();
/*32*/ } while ((random_number <= min) || (random_number >= max));
return random_number;
/*33*/ }
/*34*/
/*35*/ void randomize_sequence(value_t* sequence, int num_values)
/*36*/ {
/*37*/ // Fisher-Yates
/*38*/ for(int i = 0; i < num_values-2; i++) {
/*39*/ int random_index = random_value(i, num_values-1);
/*40*/ // Swap them
int temp = sequence[i];
/*41*/ sequence[i] = sequence[random_index];
/*42*/ sequence[random_index] = temp;
/*43*/ }
/*44*/ }
/*45*/
/*46*/ int main(int argc, char* argv[])
/*47*/ {
/*48*/ int num_values = strtoul(argv[1], NULL, 10);
/*49*/ value_t* pValues = generate_sequence(num_values);
/*50*/
/*51*/ randomize_sequence(pValues, num_values);
/*52*/
/*53*/ // Record results
/*54*/ FILE *fd = fopen("results.txt", "w+");
/*55*/ for (int i = 0; i < num_values; i++) {
/*56*/ fprintf("%i = %"PRIu64"\n", i, pValues[i]);
/*57*/ }
/*58*/ fclose(fd);
/*59*/
/*60*/ return EXIT_SUCCESS;
/*71*/ }
the posted code contains LOTS of serious problems. Specifically:
gcc -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled2.c" -o "untitled2.o"
untitled2.c: In function ‘generate_sequence’:
untitled2.c:20:35: warning: conversion to ‘size_t {aka long unsigned int}’ from ‘int’ may change the sign of the result [-Wsign-conversion]
/*20*/ value_t* data = calloc(num_values, sizeof(int));
^~~~~~~~~~
untitled2.c:22:25: warning: conversion to ‘value_t {aka long unsigned int}’ from ‘int’ may change the sign of the result [-Wsign-conversion]
/*22*/ data[i] = i;
^
untitled2.c: In function ‘randomize_sequence’:
untitled2.c:42:27: warning: conversion to ‘int’ from ‘value_t {aka long unsigned int}’ may alter its value [-Wconversion]
int temp = sequence[i];
^~~~~~~~
untitled2.c:44:41: warning: conversion to ‘value_t {aka long unsigned int}’ from ‘int’ may change the sign of the result [-Wsign-conversion]
/*42*/ sequence[random_index] = temp;
^~~~
untitled2.c: In function ‘main’:
untitled2.c:50:29: warning: conversion to ‘int’ from ‘long unsigned int’ may alter its value [-Wconversion]
/*48*/ int num_values = strtoul(argv[1], NULL, 10);
^~~~~~~
untitled2.c:58:24: warning: passing argument 1 of ‘fprintf’ from incompatible pointer type [-Wincompatible-pointer-types]
/*56*/ fprintf("%i = %"PRIu64"\n", i, pValues[i]);
^~~~~~~~
In file included from untitled2.c:5:0:
/usr/include/stdio.h:312:12: note: expected ‘FILE * restrict {aka struct _IO_FILE * restrict}’ but argument is of type ‘char *’
extern int fprintf (FILE *__restrict __stream,
^~~~~~~
untitled2.c:58:44: warning: passing argument 2 of ‘fprintf’ makes pointer from integer without a cast [-Wint-conversion]
/*56*/ fprintf("%i = %"PRIu64"\n", i, pValues[i]);
^
In file included from untitled2.c:5:0:
/usr/include/stdio.h:312:12: note: expected ‘const char * restrict’ but argument is of type ‘int’
extern int fprintf (FILE *__restrict __stream,
^~~~~~~
untitled2.c:48:21: warning: unused parameter ‘argc’ [-Wunused-parameter]
/*46*/ int main(int argc, char* argv[])
^~~~
Compilation finished successfully.
Notice that final message: Compilation finished successfully. This only means that the compiler applied some 'workaround' to each of the problems, it does NOT mean that the 'workaround' was correct.
Please correct your code so it cleanly compiles, then post a EDIT to your question
a few hints:
never access beyond argv[0] without first checking argc to assure the user actually entered the expected command line parameter.
the syntax for fprintf() is int fprintf(FILE *stream, const char *format, ...);
the syntax for strtoul() is unsigned long int strtoul(const char *nptr, char **endptr, int base);
also, regarding:
FILE *fd = fopen("results.txt", "w+");
always check (!=NULL) the returned value. If failed (I.E. ==NULL) then call
perror( "fopen failed" );
so both the error message and the text reason the system thinks the error occurred to stderr.

C Pointer Error

The program below is supposed to read a txt file and put the data in a struct. But it gives an pointer error. It gives an error in strcpy() about pointers. I'm new in C. Whats wrong?
#include <stdio.h>
#include <string.h>
int main()
{
struct citydata {
char city[20];
int temp;
};
struct citydata values[15];
struct citydata Avg;
struct citydata high;
struct citydata low;
FILE* inp;
int reccount = 0;
int x = 0;
char s;
int n;
inp = fopen("mydata.txt", "r");
if (!inp) {
printf("Unable ot open file\n");
}
while (fscanf(inp, "%s %d", s, &n) != EOF) {
strcpy(values[x].city, s);
values[x].temp = n;
x++;
}
fclose(inp);
}
Don't ignore compiler warnings.
When if you compile this code (say, with gcc), you get the following warnings:
test.c:27:24: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
while (fscanf(inp, "%s %d", s, &n) != EOF) {
^
test.c:28:32: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
strcpy(values[x].city, s);
^
In file included from test.c:2:0:
/usr/include/string.h:125:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
so, as comments suggest, you can't scan directly into the struct; you can only scan into simpler types the C standard libraries recognizes: integer, floating-point numbers, char * strings etc. Similarly, you can't perform a string copy from your structs, which are not strings.
C is a strongly-typed language with very few allowed implicit conversions. In some cases, you are able to pass integers instead of floats or vice-versa, but nothing "magically converts" into a string, or is "magically parsed" from a string.
... and there are other issues:
Note #EdHeal 's comment: If your fopen() fails, you mustn't continue running the rest of the code. Either you should exit(EXIT_FAILURE); or wrap the rest of the code in main() within an else() block.
You should printf error messages to the standard error stream, so instead of printf("error message here") it should fprintf(stderr,"error message here"). Also, the standard C library places an error code you can get as the errno variable, or you can have an error message printed to the standard error stream with the perror() function. There are a few other related related functions (like strerror(), `err() etc.) which I will not get into here.
make some mistakes with pointers=)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct citydata
{
char *city;
int temp;
} citydata;
int main()
{
char *s;
citydata *values;
values = (citydata*)malloc(sizeof(citydata) * 16);
FILE * inp;
int reccount = 0;
int x = 0;
int n;
inp = fopen("mydata.txt", "r");
if(!inp)
printf("Unable ot open file\n");
while (fscanf(inp,"%s %d",s, &n) != EOF)
{
values[x].city = (char*)malloc(sizeof(char) * 20);
strcpy(values[x].city, s);
values[x].temp = n;
x++;
}
fclose(inp);
}

I'm trying to get data from a text file delimited by tabs. but i'm unable to get the result

This is my code
#include <stdio.h>
#include <string.h>
main() {
FILE *fp;
char buff[1024];
char q1[6];
char q2[6];
char * pch;
int i;
fp = fopen("QFile.txt", "r");
fgets(buff, 255, (FILE*)fp);
pch = strtok (buff,"\t");
int count=0;
while (pch != NULL)
{
q1[0]=("%s",*pch);
pch = strtok (NULL, "\t");
}
fgets(buff, 255, (FILE*)fp);
pch = strtok (buff,"\t");
count=0;
while (pch != NULL)
{
q2[0]=("%s",*pch);
pch = strtok (NULL, "\t");
}
for(i=0;i<6;i++)
printf ("%s\n",q1[i]);
for(i=0;i<6;i++)
printf ("%s\n",q2[i]);
fclose(fp);
}
This is my QFile.txt looks like :
1 20 % of 2 is equal to 1)1 2)0.4 3)0.5 2
2 If Logx (1 / 8) = - 3 / 2, then x is equal to 1)-4 2)4 3)1/4 2
when i'm compiling, it shows some warnings:
test3.c:4:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main() {
^
test3.c: In function ‘main’:
test3.c:32:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf ("%s\n",q1[i]);
^
test3.c:35:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf ("%s\n",q2[i]);
^
I can't figure out how to correct this . I want to get two mcq questions to two arrays.How do i fix this?
test3.c:4:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main() {
^
main() defaults to returning an int. Write
int main() {
and return an int, 0 to tell the caller everything was ok
return 0; // final line of main
}
test3.c: In function ‘main’:
test3.c:32:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf ("%s\n",q1[i]);
^
test3.c:35:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf ("%s\n",q2[i]);
^
q1 and q2 are char arrays, so qx[y] gives the (y+1)th element of those arrays, i.e. a char.
If you actually want to print the character at position i, use %c (characters are casted to int, hence the warning int)
printf ("%c\n",q1[i]);
printf ("%c\n",q2[i]);

Arrays and Structs

I am taking an online college course introducing C and am completely stumped on my latest project. My professor to research online for the errors but the examples don't seem to match. I started the program on Visual Studio 2013 and now have moved to Code::blocks from the professor's instruction.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct flightRec { // declare a struct to match the format of the binary data
char FlightNum[7];
char OriginAirportCode[5];
char DestAirportCode[5];
int timestamp;
} flightRec;
int flightCmp(const void *a, const void *b) // comparison function of DestAirportCode to ascending order
{
const flightRec *p1 = (flightRec *)a;
const flightRec *p2 = (flightRec *)b;
if (p1->DestAirportCode < p2->DestAirportCode)
return -1;
else if (p1->DestAirportCode > p2->DestAirportCode)
return +1;
else
return 0;
}
int codeInst(int count, int i, char currCode, char nextCode, flightRec flightInfo[1000]) { // function that counts how many instances of each code exist
count = 0; // set count to zero
i = 0;
currCode = flightInfo[i].DestAirportCode; // get a code from the array, call it currCode
while (i < 1000 ) { // while you've not come to the end of the array
nextCode = (&flightInfo[i+1].DestAirportCode); // get the next code from the array
if (nextCode == currCode) { // if the next code equals the current code
count += 1; // then add one to count
}
else {
printf("Destination Airport Code: %s Count: %i", flightInfo->DestAirportCode, count); // else output code and count
currCode = nextCode; // set currCode to nextCode
count = 0; // set count to 0
}
++i;
}
}
int main(){
flightRec flightInfo[1000];
int i = 0;
int codeInst;
FILE* inFile = NULL;
inFile = fopen("acars.bin", "rb");
struct tm* timestamp;
if (inFile == NULL) {
printf("Could not open file acars.bin.\n");
return -1;
}
while (!feof(inFile)) {
for (i = 0; i < 1000; ++i) {
fread(&flightInfo[i], sizeof(flightInfo), 1, inFile); // read the acars.bin file into an array of these structs
}
for (i = 0; i < 1000; ++i) {
qsort(flightInfo, 1000, sizeof flightInfo, flightCmp); // sort the array
}
for (i = 0; i < 1000; ++i) {
localtime(flightInfo[i].timestamp); // Do localtime () on the timestamp member of the struct, then asctime on the time struct you get back from localtime
return timestamp;
}
int codeInst(flightInfo); // algorithm to count how many instances of each code exists
for (i = 0; i < 1000; ++i) {
printf("Flight Number: %s \nOriginal Airport: %s \nDestination Airport: %s \nDestination Airport Count:%i \nTime: %d \n\n", &flightInfo[i].FlightNum, &flightInfo[i].OriginAirportCode, &flightInfo[i].DestAirportCode, codeInst, timestamp); // print the flightRec structs in form of member columns
}
}
fclose(inFile);
system("pause");
}
Build Messages:
||=== Build: Debug in Project6 (compiler: GNU GCC Compiler) ===|
In function 'codeInst':|
|28|warning: assignment makes integer from pointer without a cast [enabled by default]|
|30|warning: assignment makes integer from pointer without a cast [enabled by default]|
||In function 'main':|
|70|warning: passing argument 1 of 'localtime' makes pointer from integer without a cast [enabled by default]|
|121|note: expected 'const time_t *' but argument is of type 'int'|
|71|warning: return makes integer from pointer without a cast [enabled by default]|
|74|error: expected declaration specifiers or '...' before 'flightInfo'|
|76|warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[7]' [-Wformat]|
|76|warning: format '%s' expects argument of type 'char *', but argument 3 has type 'char (*)[5]' [-Wformat]|
|76|warning: format '%s' expects argument of type 'char *', but argument 4 has type 'char (*)[5]' [-Wformat]|
|76|warning: format '%d' expects argument of type 'int', but argument 6 has type 'struct tm *' [-Wformat]|
83|warning: control reaches end of non-void function [-Wreturn-type]|
c||In function 'codeInst':|
|43|warning: control reaches end of non-void function [-Wreturn-type]|
||=== Build failed: 1 error(s), 10 warning(s) (0 minute(s), 0 second(s)) ===|
You have initially a function called codeInst, after that, in your main function, you declared a integer variable called codeInst, in line 73 you coded a statement that I really don't know what you want to do (int codeInst(flightInfo);).I assume that you want to call the function int codeInst and for that you must:
change the name of the variable like codeInstVarible
assign to codeInstVarible the function codeInstVarible = codeInst()
and fill all existing parameters in the function in case: (int count, int i, char currCode, char nextCode, flightRec flightInfo[1000])
Check out for info:
[c function localtime()][1]
For the error: |121|note: expected 'const time_t *' but argument is of type 'int'|
In your localtime(flightInfo[i].timestamp),
flightInfo[i].timestamp is an int, not a const time_t *(a pointer to a time_t).
For your int codeInst(flightInfo); function, it should have a return type.
In your main function, you wrote
int codeInst(flightInfo);
Which is incorrect. Look at BarbarianSpock's response.

not sure what's going on in this code

I have some C code, and I'm not quite sure what's going on.
#include <stdio.h>
#include <stdlib.h>
#define DIM1 7
#define DIM2 5
#define RES_SIZE 1000
typedef double stackElementT;
typedef struct {
stackElementT *contents;
int maxSize;
int top;
int min2;
} stackT;
void StackInit(stackT *stackP, int maxSize) {
stackElementT *newContents;
newContents = (stackElementT *)malloc(sizeof(stackElementT)*maxSize);
if (newContents == NULL) {
fprintf(stderr, "Not enough memory.\n");
exit(1);
}
stackP->contents = newContents;
stackP->maxSize = maxSize;
stackP->top = -1;
}
void StackDestroy(stackT *stackP) {
free(stackP->contents);
stackP->contents = NULL;
stackP->maxSize = 0;
stackP->top = -1;
}
int StackIsEmpty(stackT *stackP) { return stackP->top < 0; }
int StackIsFull(stackT *stackP) { return stackP->top >= stackP->maxSize-1; }
void StackPush(stackT *stackP, stackElementT element) {
if(StackIsFull(stackP)) {
fprintf(stderr, "Can't push element: stack is full.\n");
exit(1);
}
stackP->contents[++stackP->top] = element;
}
stackElementT StackPop(stackT *stackP) {
if(StackIsEmpty(stackP)) {
fprintf(stderr, "Can't pop element: stack is empty.\n");
exit(1);
}
return stackP->contents[stackP->top--];
}
int shell(char* s1, int arg) {
printf("> ");
scanf("%s %d%*c", &s1, &arg);
return arg;
}
int main() {
char cmds[DIM1][DIM2] = {{"push"}, {"pop"}, {"add"}, {"ifeq"}, {"jump"}, {"print"}, {"dup"}};
char* s1; int arg;
arg = shell(s1, arg);
printf("%s\n", &s1);
}
Input: push 4. It prints J+ instead of "push" but prints 4 normally.
It also gives these warnings on compile:
stack.c: In function ‘shell’:
stack.c:60: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char **’
stack.c: In function ‘main’:
stack.c:71: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char **’
stack.c:65: warning: unused variable ‘cmds’
stack.c:69: warning: ‘arg’ is used uninitialized in this function
Can someone please explain?
When you use the %s format specifier, it expect a value which is a pointer to the start of a string. In C, this type is char *.
Taking your main function, your variable s1 is of type char *. Therefore, s1 is a valid parameter to printf, so this line is valid:
printf("%s\n", s1);
Note the absence of an & in front of s1. In your code, you used the &, which takes the address of s1, the result of which will be of type char **. This is the wrong type, so don't use the &.
The thing is, printf can't actually tell what type its arguments are, since it is a variadic function. It simply uses whatever arguments are there, according to the types specified in the format string.
The same thing goes for scanf, but there is a pitfall: you must make sure that enough memory is allocated to account for the user input, else you will experience a buffer overflow with unpredictable results. Aside from this, printf and scanf are perfectly complementary.
Anyhoo, this takes care of the compiler warnings, aside from the unused cmds variable (it's unnecessary in the provided code). Also, there is the part of args - it really should be a variable declared inside of shell, and not passed as a parameter, since its value is not even used inside shell.
Don't know what's up with the rest of the code. It's superfluous considering your main function only calls on shell.

Resources