I want to compute the checksum of a txt file using C in mac, thus I wrote a simple program as
#include <iostream>
#include <stdio.h>
using namespace std;
int main() {
FILE *in;
char buff[512];
if(!(in = popen("shasum ritesh_file_test.txt", "r")))
{
return 1;
}
while(fgets(buff, sizeof(buff), in)!=NULL)
{
cout << buff;
}
printf ("checksum = %s",buff);
pclose(in);
return 0;
it prints the checksum of txt file , but also it prints the path of file. as
30b574b4ddbc681d9e5e6492ae82b32a7923e02e ritesh_file_test.txt
How do I get rid of this path and only access the checksum value?
The output format of shasum is of form
<HASH> <Filename>
so, the hash value and the file name are separated by a space. One possible way, to separate the hash from the complete outpuy, is to tokenize buff before printing.
You can make use of strtok() and use space () as delimiter to take out only the checksum value.
That said, in C, you don't include #include <iostream>, don't use using namespace std; and don't write cout. Moreover, use a C compiler to compile C code.
Three solutions:
Since you are using a shell, shasum ritesh_file_test.txt | awk '{ print $1; }' might work.
Since you are using C++:
std::string checksum(buff);
checksum = checksum.substr(0, checksum.find(' ') -1 );
Or even, since a hash is always 40 bytes:
std::string checksum(buff, 40);
I leave error checking as an exercise for you!
Related
I'm trying to create a simple script on my server, basically I would like to sent a string and display it via system function...
#include <stdio.h>
int main()
{
char txt[100];
printf("Insert a text: ");
fgets(txt, 100, stdin);
system("echo %s"), txt;
return 0;
}
Rght now I'm not getting any string just "%s"
any idea why?
system("echo %s"), txt;
This isn't doing what you think; it's an expression which evaluates to txt. Since evaluating txt has no side effects, and since you're not capturing the result of the expression anywhere, adding , txt after the system call essentially does nothing. See this question for some information on the "comma"-operator in C.
Moreover, system doesn't support the use of printf-style format specifiers, so the %s in your string literal doesn't have any special meaning; it's just going to be echoed exactly as written, as you've seen. If you want to construct a command at runtime for use with system, you will have to do so with sprintf or similar.
The prototype to system() is:
int system(const char * command);
From man 3 system:
executes the shell command specified in command
From this we can safely assume s refers to a C-"string".
So prepare the string using for example snprintf():
char s[1024];
snprintf(s, 1024 -1, "echo %s", txt); /* -1 for the C-"string"'s 0-terminator */
Then pass it:
system(s);
Instead of system("echo %s"), txt; try this:
printf("%s", txt);
the system statement will not format the output, like printf.
suggest using:
#include <stdio.h>
#include <stdlib.h> // system()
#include <string.h> // strcpy(), strcat()
#define BUF_LEN (100)
int main()
{
char output[10+BUF_LEN] = "echo ";
char txt[BUF_LEN] = {'\0'};
printf("Insert a text: ");
fgets(txt, BUF_LEN, stdin);
strcat( output, txt );
system( output );
return 0;
}
The above code works very nicely, however;
do not include any command separators, semicolons, or other characters that would be interpreted by the shell in the input string.
I want to take the output of the grep command on a file, create a new file and save that grep output to the new created file, can someone please point me to the right direction in how I would do that?
The path you choose depends a great deal on how simple you want it to be.
Perhaps the simplest method is the use of system:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
system ("grep a *.c >outfile.txt");
return 0;
}
though you also could construct the command dynamically if you have different arguments to grep or a non-fixed output file.
Beyond that, you could use popen() (if available on your implementation - it's not mandated by ISO but is instead a POSIX thing) along with fgets() or fgetc() to read the output of that command and do whatever you want with it:
#include <stdio.h>
int main (void) {
int chr;
FILE *echo = popen ("echo hello there", "r");
if (echo != NULL) {
while ((chr = fgetc (echo)) != EOF)
putchar (chr);
fclose (echo);
}
return 0;
}
The next step up from there may be to not rely on an external grep at all but instead include something like PCRE (Perl-compatible regular expressions) into your own code, giving you much finer control over what happens.
I am writing a program which should do multiple things including prompting the user for the name of the input file which I have done, but I am having troubling implementing a process where the program processes each line from a file, storing it as a struct data structure, finally using the malloc, calloc commands it will store all the valid records in memory to be validated. So any help on how to do this would be helpful.
#include <stdio.h> //library including standard input and output functions
#include <stdlib.h> //library including exit and system functions used below
#include <string.h> //library including string functions used
struct packet{
int source;
int destination;
int type; // Varibles for the structure
int port;
char data[50];
char * filename;
};
int main ()
{
printf("**************Details*******************************\n");
printf("*****Student name: ***********************\n");
printf("*****Course name: *******\n");
printf("*****Student ID: ************************ \n");
printf("\n");
// The program must prompt for the name of the input file. If it doesn't exist the program should stop with an error message
FILE *DataFile;
char filename[10] = { '\0' } ;
char DataLine[70];
printf("Enter the filename you wish to open\n");
scanf("%s", &filename);
if (( DataFile = fopen(filename, "r")) == NULL)
{
printf ("*****file could not be opened. : %s\n", filename);
exit(1);
}
// Read the data from this file
char *fgets(DataLine, 70, (FILE) *DataFile);
system("pause");
return 0;
}
Here is the text file the program should take the data from
0001:0002:0003:0021:CLS
0001:0010:0003:0021:CLS
0001:0002:0002:0080:<HTML>
0005:0002:0002:8080:<BR>
0005:0012:0002:8080:<BR>
0001:0002:0002:0080:<BODY>
0005:0002:0002:8080:<B>HELLO</B><BR>
0002:0004:0002:0090:100000000000000000022
0001:0002:0003:0021:DEL
0002:0004:0002:0010:100000000000000000023
Each colon from the file shows what part of the packet structure it should be a part of, i.e. the first set of 4 numbers is the "source" then "destination and so forth.
One way to do this is :
Use fgets to read the file line by line.
For each line, use strtok to tokenize the string.
For each of the first four tokens, use strtol to convert it to an integer.
A. The line char *fgets(DataLine, 70, (FILE) *DataFile); should probably just read fgets(DataLine, 70, DataFile);
B. If you create a single variable you don't really need malloc since the compiler will allocate it, but if you are planning on creating an array of Data you will only need to call malloc once to create the whole array, something like:
struct packet* packetarr = malloc(sizeof packetarr * DESIRED_ARRAY_SIZE);
C. As downHillFromHere suggested, use strtok to get each part of the string and strtol to convert the read strings to numbers when appropriate.
I'm quite new to Linux and not familiar with C. Here I have one question about both.
I'm writing a C program to run in Linux. And I have a file names f.txt in the same folder. With some fields like this:
Jason 12 Male
I want to compare the $2 of the txt file of each line with the value of parameter a. If the second field of the line is greater than a, then print the first field $1.
I tried codes like this but not work. Can anybody help? Thanks!
void main()
{ int a;
scanf("%d",&a);
char* comm="awk '{if($2>"+a+") print $1}' f.txt";
system(comm);
}
For your stated problem, which is just basic text file processing, it is probably easiest to solve this task using a scripting language itself, rather than using C (such as python, perl, or awk itself).
For your programming problem, the C language does not support that kind of string concatenation. You have to build the string using a call to snprintf() (or via calls to strcat()).
char comm[512];
int r = snprintf(comm, sizeof(comm), "awk '{if($2>%d) print $1}' f.txt", a);
if (r < 0) {
/* error */
} else if (r < sizeof(comm)) {
/* ok */
} else {
/* need a bigger comm buffer... */
}
An alternative approach to handling this problem would be the following: Read the bytes from stdin with the following snippet:
while ( ( char *data = scanf( "%s %d %s\n" ) ) != EOF )
... where the newline is your delimiter. Then you can perform the appropriate actions on "data" to access each field individually.
It would be ran by piping your text file to the program:
./program < textfile.txt
This error is driving me nuts. Please help. The code compiles in gcc in terminal and in codeblocks IDE. I'm using Linux and C. It compiles and runs but theres no output in the second text file "onlydata.txt".
#include <stdlib.h>
#include <stdio.h>
/* Data Looks Like This...
E1 101223 9.2
E1 120231 8.4
E2 121212 400.2
I need this....
9.2
8.4
*/
struct Data
{
char *specimen;
int date;
double result;
};
int main()
{
char szBuffer[256];
unsigned int iCt=0;
Data* pData=NULL;
FILE* fpIn=NULL;
fpIn=fopen("data.txt","r"); //Open "Data.dat for read "r" access.
if(fpIn) //and loop through data to count lines.
{ //in iCt
while(!feof(fpIn))
{
fgets(szBuffer,256,fpIn);
iCt++;
}
fclose(fpIn);
}
printf("iCt = %d\n\n",iCt); //Allocate a buffer of Data type
pData=(Data*)malloc(iCt*sizeof(Data)); //to hold iCt objects
if(pData)
{
fpIn=fopen("Data.txt","r"); //Open "Data.dat for read "r" access.
if(fpIn) FILE *fp=NULL;
{
iCt=0;
while(!feof(fpIn)) //read data from text file into buffer
{
fscanf(fpIn,"%s%i%f",
&pData[iCt].specimen,
&pData[iCt].date,
&pData[iCt].result);
// printf("%10.2f\t%4.2f\t%f\t%f\t%f\t%u\t%4.2f\n",
// pData[iCt].specimen,
// pData[iCt].date,
// pData[iCt].result,
iCt++;
FILE *np=NULL;
np = fopen("onlydata.txt","w");
if(np)
fprintf (np," ", &pData[iCt].result);
fclose(np);
}
fclose(fpIn);
}
free(pData);
}
getchar();
return 0;
}
Linux filenames are case sensitive. The second fopen() will fail if the file is called "data.txt".
The actual problem you have stems from the following line:
fprintf (np," ", &pData[iCt].result);
It simply outputs a space to the file. I think you forgot a %f.
EDIT Missed the other obvious error noted by Didier Trosset. :)
you need to have specifier in your fprintf for the result, without the specifier it just writes a whitespace into the file
You should open you destination file only once, at the same time you open your source file.
Right now, for every line of the source file, you open the destination, truncate it, and write one line. In the end, you only got a single line (the last one) in your destination file.
Furthermore, your fprintf does only write a single space character: your format string should be "%f" or at least contain one %f. Actually, the parameter &pData[iCt].result is not used.
Note also that this parameter should not be passed by address, but by value: (remove the &).