Error with fread() in c, not having expected outut - algorithm

I'm making a checksum algorithm for one of my classes, I want to read two binary files and run them through a checksum algorithm. The checksum algorithm works (I've tried inputting what I want into the terminal and it works) but I can't get my fread() to work. I've tried printing the outputs and they print the correct stuff, but then a bunch of other random numbers and letters at the end.
Here is my code:
int main(int argc, char *argv[])
{
FILE *ptr1;
FILE *ptr2;
ptr1 = fopen("test1.bin","rb");
ptr2 = fopen("test2.bin","rb");
char file1[sizeof(ptr1)], file2[sizeof(ptr2)];
char sum[sizeof(ptr1)], comp[sizeof(ptr1)];
fread(file1,sizeof(file1),1,ptr1);
fread(file2,sizeof(file2),1,ptr2);
fclose(ptr1);
fclose(ptr2);
/* char file1[20], file2[20];
char sum[20], comp[20];
printf("enter 1\n");
scanf("%s",&file1);
printf("enter 2\n");
scanf("%s",&file2);*/
if(strlen(file1)==strlen(file2)) {
char next='0';
int length = strlen(file1);
for(int i=length-1;i>=0;i--)
{
if(file1[i]=='0' && file2[i]=='0' && next=='0')
{
sum[i]='0';
next='0';
}
else if(file1[i]=='0' && file2[i]=='0' && next=='1')
{
sum[i]='1';
next='0';
}
else if(file1[i]=='0' && file2[i]=='1' && next=='0')
{
sum[i]='1';
next='0';
}
else if(file1[i]=='0' && file2[i]=='1' && next=='1')
{
sum[i]='0';
next='1';
}
else if(file1[i]=='1' && file2[i]=='0' && next=='0')
{
sum[i]='1';
next='0';
}
else if(file1[i]=='1' && file2[i]=='0' && next=='1')
{
sum[i]='0';
next='1';
}
else if(file1[i]=='1' && file2[i]=='1' && next=='0')
{
sum[i]='0';
next='1';
}
else if(file1[i]=='1' && file2[i]=='1' && next=='1')
{
sum[i]='1';
next='1';
}
else
break;
}
for (int i=0;i<length;i++)
{
if(sum[i]=='0')
comp[i]='1';
else
comp[i]='0';
}
if(next=='1')
next='0';
else
next='1';
printf("\nChecksum=%c%s",next, comp);
}
else {
printf("\nInput Lengths do not match");
}
}
test1.bin and test2.bin are two files that contain 8 bytes of binary. I've tried using
printf("this is file 1 %s\n", file1)
printf("this is file 2 %s\n", file2)
to help debug and it outputs
this is file 1 01001001dL
this is file 2 01001000P5L
What is my error here? I'm not great at C so I'm sure its something simple.

You allocate sizeof(ptr1) bytes for file1, but that means the size of the type FILE*, which is likely to be 4. If you know your file contains exactly 8 bytes, do write 8 there.

Related

Im using putty for a class assignment and I am getting a segmentation fault

Write a C program that counts the number of non white-space characters in an input text file. Program takes as command argument(s) the name of the input file (and the output file with option -f). Based on the option flags, it displays the output on the standard output, or writes the output to an output file. (25 points)
The command format is as follows:
command -f inputfile outputfile
or,
command -s inputfile
-f indicates writing to an output file;
-s indicates displaying the output on the screen.
I am receiving the segmentation fault on the -s command
#include <stdio.h>
#define BLANK ' '
#define NEWLINE '\n'
int main(int argc, char *argv[])
{
FILE *infile;
char c;
int char_count=0;
FILE *outfile;
outfile = fopen(argv[3], "w");
//checks for the argc length to be within the correct perameteres
if ((argc < 3) || (argc > 4))
{
printf("Incorrect format, please try gain\n");
exit(1);
}
//checks the input file to see if it is empty
if ( (infile= fopen(argv[2], "r")) == NULL)
{
fprintf(stderr,"%s: cannot open %s \n", argv[0], argv[1]);
exit(1);
}
// count the number of charecters in infile
while ( (c = getc(infile)) != EOF)
if ((c != BLANK) && (c != NEWLINE) )
char_count++;
//checks to see if the command is -s or not, outputing the corrct message to the desired location
if (argv[1] == "-s")
{
printf("%d characters\n", char_count);
}
else
{
fprintf(outfile, "%s contains %d characters\n", argv[2], char_count);
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BLANK ' '
#define NEWLINE '\n'
int main(int argc, char *argv[])
{
FILE *infile;
FILE *outfile;
char c;
int char_count=0;
//checks for the argc length to be within the correct perameteres
if ((argc < 3) || (argc > 4))
{
printf("Incorrect format, please try gain\n");
exit(1);
}
//checks if passed second argument is valid (-f or -s)
if (strcmp(argv[1], "-f") == 0) {
if (argc < 4) {
fprintf(stderr, "Please inform output file. Usage: -f inputfile outputfile");
exit(1);
}
outfile = fopen(argv[3], "w");
}
else if (strcmp(argv[1], "-s") != 0) {
fprintf(stderr, "Parameter not recognized: %s\n", argv[1]);
exit(1);
}
//checks the input file to see if it is empty
if ( (infile= fopen(argv[2], "r")) == NULL)
{
fprintf(stderr,"%s: cannot open %s \n", argv[0], argv[1]);
exit(1);
}
// count the number of charecters in infile
while ( (c = getc(infile)) != EOF)
if ((c != BLANK) && (c != NEWLINE) )
char_count++;
//checks to see if the command is -s or not, outputing the corrct message to the desired location
if (strcmp(argv[1], "-s") == 0)
{
printf("%d characters\n", char_count);
}
else
{
fprintf(outfile, "%s contains %d characters\n", argv[2], char_count);
printf("Result written to %s\n", argv[3]);
}
return 0;
}

go error % not allowed

I have written a program for Mumax with a go syntax but I don't understant my error. Here the script where the error appears :
n:=0
Dtr0:=5*1e-12
Dtd0 :=300*1e-12
Dtf0:=5*1e-12
Dtz0:=20000*1e-12
tr0:=Dtr0
td0:=Dtd0+tr0
tf0:=Dtf0+td0
tz0:=Dtz0+tf0
TT:=tz0
n=t/TT
tr:=tr0+(n*TT)
td:=td0+(n*TT)
tf:=tf0+(n*TT)
tz:=tz0+(n*TT)
if (n % 2 == 0) {
if (n<1 && t<tr) {
a:=(t/tr)
} else if (n>=1 && t>=tz0+((n-1)*TT) && t<tr) {
a:=1/(tr-(tz0+((n-1)*TT)))*(t-(tz0+((n-1)*TT)))
} else if (t>=tr && t<=td) {
a:=1
} else if (t>td && t<=tf) {
a:=(-1/(tf-td))*(t-td)+1
} else if (t>tf && t<tz) {
a:=0
}
}
if (int(n)%2==1) {
if (n<1 && t<tr) {
a:=-(t/tr)
} else if (n>=1.0 && t>=tz0+((n-1)*TT) && t<tr) {
a:=-(1/(tr-(tz0+((n-1)*TT)))*(t-(tz0+((n-1)*TT))))
} else if (t>=tr && t<=td) {
a:=-1
} else if (t>td && t<=tf) {
a:=-((-1/(tf-td))*(t-td)+1)
} else if (t>tf && t<tz) {
a:=0
}
}
And the error message is : line 37: if (n % 2 == 0) {: not allowed: %
Thank's a lot
There are two problems here:
n must be a float because TT must be a float, because that's ultimately a function of two floats. This conflicts with the n := 0 default int definition at the top.
the modulus operator on floats is undefined (see this playground for what happens when you try).
This means you have a very weird Go implementation or we're not seeing everything.
In any case, either you have to either coerce n to an int (as you do in your second if) or use math.Mod somehow.

Building simple unix shell problems

I am new with unix and I've got an assignemnt on college to build a simple shell in c with built in cd and kill command..
This is my code which is not working..tbh I dont understand it the best so Im not suprised it is not working.. can you help me with it? Also have no idea how I would implement kill command. thank you!
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define BUF_SIZE 1024
const int ARGSIZE = 20;
void execute(char*args[])
{
int pid, status;
pid = fork();
if(pid<0)
{
perror("Error forking!");
}
else if(pid > 0)
{
while(wait(&status) != pid)
continue;
}
else if(pid == 0)
{
if (execvp(args[0], args) == -1)
{
perror("Error");
}
}
}
void cd(char*directory)
{
int ret = 0;
if(directory == '\0')
directory = getenv("HOME");
ret = chdir(directory);
if(ret != 0)
fprintf(stderr,"Failed to enter directory: %s\n",directory);
else
printf("%s\n",directory);
}
int main()
{
char line[BUF_SIZE];
char *args[ARGSIZE];
int argIndex = 0;
while(1){
printf("> ");
fgets(line, BUF_SIZE, stdin);
char *token;
token = strtok(line," ");
while(token!=NULL)
{
args[argIndex]=token;
token = strtok(NULL," ");
argIndex++;
}
args[argIndex]=NULL;
if(strcmp(args[0], "quit") == 0 || strcmp(args[0], "exit") == 0)
break;
if(line== "\n")
printf("> ");
else if ((strcmp(args[0], "cd") == 0))
cd(args[1]);
else
execute(args);
}
return 0;
}
You were on the right track. There were a few subtle issues where you were not accounting for the trailing '\n' that would remain in line as the last character following whatever was entered at the prompt. Including " \n" in the delimiters used to tokenize the input with strtok will remove it, allowing valid strcmp comparisons with the final token (e.g. that is why quit and exit would not quit the application).
Other than than, there were several additional things you could do a little different/better, you could handle directories entered as e.g. '~/somedir', and similar additional checks that could be employed. I have notated most below as comments to the code.
Look over the changes below and let me know if you have any questions. There are always additional checks that can be added, etc.., but on balance your approach to the problem was pretty good. (note: some of the changes made were non-substantive, e.g. "shell> " as the prompt, instead of "> ". Just handle any of those as you wish.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
enum {ARGSIZE = 20, BUF_SIZE = 1024};
void execute (char **args);
void cd (char *directory);
int killpid (char *pitstr, int sig);
int main (void)
{
char line[BUF_SIZE] = {0};
char *args[ARGSIZE] = {NULL};
char *token;
int i, argIndex = 0;
while (1) {
argIndex = 0; /* reinitialize variables */
for (i = 0; i < ARGSIZE; i++)
args[i] = NULL;
printf ("shell> "); /* prompt */
if (fgets (line, BUF_SIZE, stdin) == NULL) {
printf ("EOF received\n");
return 0;
}
if (*line == '\n') /* Enter alone */
continue;
token = strtok (line, " \n"); /* add \n to delimiters */
while (token != NULL) {
args[argIndex] = token;
token = strtok (NULL, " \n");
argIndex++;
}
if (!argIndex) continue; /* validate at least 1 arg */
if (strcmp (args[0], "quit") == 0 || strcmp (args[0], "exit") == 0)
break;
/* handle 'cd' or 'kill' separately */
if ((strcmp (args[0], "cd") == 0))
cd (args[1]);
else if ((strcmp (args[0], "kill") == 0)) {
if (args[1]) killpid (args[1], SIGTERM);
}
else
execute (args);
}
return 0;
}
void execute (char **args)
{
int pid, status;
pid = fork ();
if (pid < 0) {
perror ("Error forking!");
return;
}
else if (pid > 0) {
while (wait (&status) != pid)
continue;
}
else if (pid == 0) {
if (execvp (args[0], args) == -1) {
perror ("Error");
}
_exit (EXIT_FAILURE);
}
}
void cd (char *directory)
{
char dir[BUF_SIZE] = {0};
if (!directory) { /* handle 'cd' */
directory = getenv ("HOME");
if (chdir (directory))
fprintf (stderr, "Failed to enter directory: %s\n", directory);
else
printf ("%s\n", directory);
return;
}
if (*directory == '~') { /* handle cd ~/stuff */
strcpy (dir, getenv ("HOME"));
strcat (dir, "/");
strcat (dir, directory + 2);
if (chdir (dir))
fprintf (stderr, "Failed to enter directory: %s\n", dir);
else
printf ("%s\n", dir);
return;
}
if (chdir (directory)) /* handle given directory */
fprintf (stderr, "Failed to enter directory: %s\n", directory);
else
printf ("%s\n", directory);
}
int killpid (char *pidstr, int sig)
{
pid_t pid = (pid_t)atoi (pidstr);
if (pid < 1) {
fprintf (stderr, "warning: requested pid < 1, ignoring\n");
return (int)pid;
}
printf (" killing pid '%d' with signal '%d'\n", (int)pid, sig);
// return kill (pid, sig);
return 0;
}
Sample Usage/Output
$ ./bin/ushell
shell> cd
/home/david
shell> cd ~/tmp
/home/david/tmp
shell> kill 18004
killing pid '18004' with signal '15'
shell>
shell> quit

How to create | in one's own shell?

I'm actually doing my own shell.
I have done the following special characters:
int commande(int fin, int fout, char * com, char * param, int * bg){
// execute a command
(ex. ls –l)
int symbole;
char *mot;
pid_t pid;
symbole = parsing();
switch(symbole){
case 0: // NL
case 1: // ;
case 2: // &
case 3: // <
case 4: // >
case 5: // | (Here I have some issues when I try to redirect the output of a command).
(correspond à ctrl+D)
case 10:// Mot
default:
}
return;
}
But I have some issues to do the redirection of an output when it is piped " |", when I have two instructions that follow themselves. Indeed I have tried the following operations which have all worked:
>myShell ps > fich
>myShell ls -l | wc -l
But not this one:
>myShell ls -l | wc -l >file
here are the two cases specifically developped. I think that the issue is in the case 5 and not in the case 4 because the first command I tried worked (which I shew you above).
case 4: // SYMBOLE : >
if(output==0){
output=1;
execute=1;
for (l=0;l<10;l++){
eltsoutput[l]=eltsCommande[l];
}
}
break;
case 5: // SYMBOLE : |
//if(tube==0){
/*for (l=0;l<10;l++){
eltstube[l]=eltsCommande[l];
}*/
p2=fork();
if(p2==0){
if(tube==0){
freopen( "fichtmp", "w", stdout );
execvp(eltsCommande[0], eltsCommande);
}
return(0);
}
else{ if(background==0){ // SANS MOD BG ATTENDRE FIN FILS
waitpid(p2, NULL, 0);
}
tube=1;
execute=1;
}
break;
Can you help me finding a way to execute two commands at the same time with | and that allow their result to go to a file?
In my shell, the case one work in the case of a redirection with an instruction ";":
}else if(output==1){
close(1);
int filew = creat(eltsCommande[0], 0644);
execvp(eltsoutput[0], eltsoutput);
Maybe I should use this code to make it work?
Looking at the NetBSD /bin/sh source code, I see the following pipe implementation:
static int
sh_pipe(int fds[2])
{
int nfd;
if (pipe(fds))
return -1;
if (fds[0] < 3) {
nfd = fcntl(fds[0], F_DUPFD, 3);
if (nfd != -1) {
close(fds[0]);
fds[0] = nfd;
}
}
if (fds[1] < 3) {
nfd = fcntl(fds[1], F_DUPFD, 3);
if (nfd != -1) {
close(fds[1]);
fds[1] = nfd;
}
}
return 0;
}
This function is called by evalpipe with 2 file descriptors:
STATIC void
evalpipe(union node *n)
{
struct job *jp;
struct nodelist *lp;
int pipelen;
int prevfd;
int pip[2];
TRACE(("evalpipe(0x%lx) called\n", (long)n));
pipelen = 0;
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
pipelen++;
INTOFF;
jp = makejob(n, pipelen);
prevfd = -1;
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
prehash(lp->n);
pip[1] = -1;
if (lp->next) {
if (sh_pipe(pip) < 0) {
if (prevfd >= 0)
close(prevfd);
error("Pipe call failed");
}
}
if (forkshell(jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) {
INTON;
if (prevfd > 0) {
close(0);
copyfd(prevfd, 0, 1);
close(prevfd);
}
if (pip[1] >= 0) {
close(pip[0]);
if (pip[1] != 1) {
close(1);
copyfd(pip[1], 1, 1);
close(pip[1]);
}
}
evaltree(lp->n, EV_EXIT);
}
if (prevfd >= 0)
close(prevfd);
prevfd = pip[0];
close(pip[1]);
}
if (n->npipe.backgnd == 0) {
exitstatus = waitforjob(jp);
TRACE(("evalpipe: job done exit status %d\n", exitstatus));
}
INTON;
}
evalpipe is called in a switch statement in evaltree as follows:
case NPIPE:
evalpipe(n);
do_etest = !(flags & EV_TESTED);
break;
... which is called by the infinite loop in evalloop, and percolates up the tree till it gets to the eval function. I hope this helps.

Sending child stdout to parent stdout

I am working on a simple application that takes the output from another one and writes it to a socket.
Below is the code for the application that I am execvp'ing
this code is called simple App
int main( int argc, char * argv[])
{
int count = 0;
while(count < 5)
//Attempt fork
if((pid2 = fork()) < 0) //Failed to fork
{
printf("\n Failed to fork in Dump \n");
exit(1);
}
else if (pid2 == 0) //Child Code
{
dup2(STDOUT_FILENO,pipefd[1]);
close(pipefd[0]);
close(STDOUT_FILENO);
if(execvp("../App/App", dumpParam) < 0) //execute the app; returns -1 if failed
{
printf("\nFailed to execute App\n");
exit(1);
}
}
else //Parent
{
close(pipefd[1]);
memset(buff,'0',sizeof(buff));
printf("here\n");
while( (r = read(pipefd[0],buff,sizeof(buff))) >= 0)
{
printf("\nSuccess in read r = %d\n",r);
printf("\nBuff = %s\n",buff);
memset(buff,'0',sizeof(buff));
}
printf("nowHere\n");
}
return pipefd[0];
so far when i run it, it prints out just a ton of 0's. if i set read > 0 then it doesn't run at all. Thoughts?
The read is returning 0 (end of file) because the child end of the pipe is closed.
You've got the dup2 the wrong way round, it should be
dup2(pipefd[1],STDOUT_FILENO)
also remove
close(STDOUT_FILENO)

Resources