Linux File Read and Write - C++ - c++

I supposed to create a program that reads source.txt's first 100 characters, write them in destination1.txt, and replace all "2" to "S" and write them to destination2.txt. Below is my code
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdio>
#include <iostream>
using namespace std;
int main(int argc, const char* argv[]){
argv[0] = "source.txt";
argv[1] = "destination1.txt";
argv[2] = "destination2.txt";
int count=100;
char buff[125];
int fid1 = open(argv[0],O_RDWR);
read(fid1,buff,count);
close(fid1);
int fid2 = open(argv[1],O_RDWR);
write(fid2,buff,count);
close(fid2);
//How to change the characters?
return 0;
}
Thanks guys I am able to do the copying. But how to perform the character replacement? If it's fstream I know how to do it with a for loop. But I'm supposed to use Linux system calls.

Define an array out_buf and copy buff into out_buf character by character, replacing 2's to S.
...
read(fid1,buff,count);
close(fid1);
char out_buf [125];
int i;
for (i = 0; i < sizeof (buf); i++) {
if (buff [i] == '2')
out_buf [i] = 'S'
else
out_buf [i] = buff [i]
}
int fid2 = open(argv[1],O_RDWR);
write(fid2, out_buf,count);
close(fid2);
return 0;

You should replace the filename assignments to something like this:
const std::string source_filename = "source.txt";
const std::string dest1_filename = "destination1.txt";
const std::string dest2_filename = "destination2.txt";
There is no guarantee that the OS will allocate 3 variables to your program.

Related

Trying to copy strings without last characters using memcpy

Newbie quetion here.
So i have a const char* and need to copy it to a char* without the last two character.
I already tried to use strncpy but i'm using c++ in vs and says it is deprectated.
I cannot use std::string.
Using memcpy prints me trash. I want to print adress but it prints me adress²²²²Üw
I will put my code here:
#include <cstring>
#include <iostream>
#include <stdio.h>
int main()
{
const char* ident = "adress.P";
char* tm_name;
if( (tm_name = (char*)malloc(sizeof(char) * (strlen(ident) - 2))) != NULL)
memcpy( tm_name, ident, strlen(ident) - 2);
printf("tm_name = %s", tm_name);
return 0;
}
best regards,
Guilherme Gil
i did not put '\0' xD
thx guys!
Now the code looks like this:
#include <cstring>
#include <iostream>
#include <stdio.h>
int main()
{
const char* ident = "adress.P";
char* tm_name;
int ident_size = strlen(ident);
if ((tm_name = (char*)malloc(sizeof(char) * (ident_size - 1))) != NULL) {
memcpy(tm_name, ident, ident_size - 1);
tm_name[ident_size - 2] = '\0';
}
printf("tm_name : %s , size = %d", tm_name, strlen(tm_name));
return 0;
}
And the output is:
tm_name : adress , size = 6
Thanks again!

How can I solve this problem, i need to export a line from a text file?

I have an input file like this:
Virtual (A) (A) (A) (A) (A) (A) (A) (A) (A) (A) (A) (A)
The electronic state is 1-A.
Alpha occ. eigenvalues -- -0.26426 -0.26166 -0.25915 -0.25885
Alpha occ. eigenvalues -- -0.25284 -0.25172 -0.24273 -0.23559
Alpha occ. eigenvalues -- -0.20078 -0.19615 -0.17676 -0.10810
Alpha virt. eigenvalues -- -0.07062 -0.06520 -0.05969 -0.01767
Alpha virt. eigenvalues -- -0.01604 -0.00951 -0.00428 0.00041
I would like to export the first line obtaining first 11 characters " Alpha virt.". How should I do? I code by C++ language as below code, but it cant finish while loop functio. I dont know why, I am a fresher. Please help me. Thank you so much.
My C++ code:
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#define FILENAME "filelog.txt"
using namespace std;
int main(void) {
char* line_buf = NULL;
size_t line_buf_size = 0;
int line_count = 0;
string s;
std::string dongsosanh = " Alpha virt.";
FILE* fp = fopen(FILENAME, "r");
getline(&line_buf, &line_buf_size, fp);
std::string STRR(line_buf, 11);
do {
line_count++;
getline(&line_buf, &line_buf_size, fp);
} while(STRR.compare(dongsosanh) != 0);
std::cout << STRR << endl;
return 0;
}
Thank you so much.
Many problems with your program:
line_buf - does not have memory allocated, undef behaviour
line_count - is 0, nothing will be red
You are not closing file at the end.
" Alpha virt." - this line will never be found, it has space at the begining.
STRR is never updated after line has been red, endless loop
Working solution:
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#define FILENAME "filelog.txt"
using namespace std;
int main(void) {
const std::string dongsosanh = "Alpha virt.";
char* line_buf = new char[100];
size_t line_buf_size = 100;
int line_count = 0;
string s;
FILE* fp = fopen(FILENAME, "r");
do {
line_count++;
getline(&line_buf, &line_buf_size, fp);
std::cout << line_buf;
} while(dongsosanh.compare(0, 11, line_buf, 11));
free(line_buf);
fclose(fp);
return 0;
}
This is to show how it works in your case, but you should use vector instead of char* line_buf.
You could just do this:
std::ifstream input(FILENAME);
std::string line;
while(std::getline(input, line)) {
if(line.substr(0, 11) == "Alpha virt.") {
std::cout << line << endl;
return 0;
}
}
EDIT: added the return statement to make sure only the first line starting with 'Alpha virt.' is printed.

Possible memory leak in string memory allocation

This is my code:
#include <string>
#include <iostream>
#include <cstdio>
#include <cstdlib>
std::string & fileread(const char * name)
{
FILE *fp = fopen(name,"rb");
size_t sz;
int i;
char *buff;
fseek(fp, 0, SEEK_END);
sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
buff = (char *)malloc(sizeof(char)*(sz+1));
buff[sz] = '\0';
fread(buff,sz,1,fp);
std::string * rtstr = new std::string(buff);
free(buff);
fclose(fp);
return * rtstr;
}
int main(int argc,char * argv[])
{
std::string file_info(fileread(argv[1]));
std::cout<<file_info << std::endl;
return 0;
}
It is simply read one file, and print its content to screen.
In the function fileread, I use new std::string(buff); to get a std::string *, and return the point back. Will it cause memory leak? And if the answer is 'yes' , how to avoid it?
About use C in C++: fread is much faster than ifstream (tested with 1 billion random number)
My problem is about memory leak.
Return std::string by value. Don't worry, C++ will take care of not copying the object redundantly (unless you have a very old compiler).
Here is the code, fixed:
#include <string>
#include <iostream>
#include <cstdio>
#include <cstdlib>
std::string fileread(const char * name)
{
FILE *fp = fopen(name,"rb");
size_t sz;
int i;
char *buff;
fseek(fp, 0, SEEK_END);
sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
buff = (char *)malloc(sizeof(char)*(sz+1));
buff[sz] = '\0';
fread(buff,sz,1,fp);
std::string rtstr(buff);
free(buff);
fclose(fp);
return * rtstr;
}
int main(int argc,char * argv[])
{
std::string file_info(fileread(argv[1]));
std::cout<<file_info << std::endl;
return 0;
}
I made only the small change necessary and ignored any other problems you might have in your code. Take care.
As Nawaz rightly commented: "DONT code C in C++. Use std::ifstream and std::string (not std::string*)". Here is the code in C++ to avoid all the issues:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("myfile.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}

Program that returns a list of drive letters

In the example of my computer the desired output should be: "C: E: F: H: N:" . I know it's possible, but what is the simpliest way to do that? Pottering in QueryDosDevice output
#ifndef UNICODE
#define UNICODE
#endif
#include <Windows.h>
#include <fstream>
#include <iostream>
const int REPORT_LENGTH = 5000;
int main(void)
{
TCHAR targetPath[REPORT_LENGTH];
std::ofstream oFile;
oFile.open("dos device query.txt");
QueryDosDevice(NULL,targetPath,REPORT_LENGTH);
for(int i=0; i<REPORT_LENGTH;i++)
if (targetPath[i]=='\0')(targetPath[i]='\n');
for(int i=0; i<REPORT_LENGTH; i++)
oFile<<static_cast<char>(targetPath[i]);
oFile.close();
return 0;
}
would be a huge waste of time and resources. Also function GetLogicalDriveStrings has betrayed me a lot.
#include <Windows.h>
int main()
{
TCHAR buffer[50];
GetLogicalDriveStrings(50,buffer);
MessageBox(0,buffer,"Drives in the system",MB_OK);
return 0;
}
It shows only the "C:\" volumine.
Example with GetLogicalDrives, albeit not with concatenating to a string (which is left as an exercise to the OP and the readers ;)):
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
int __cdecl _tmain(int argc, _TCHAR *argv[])
{
// Get the bit mask of drive letters
DWORD drives = ::GetLogicalDrives();
// Go through all possible letters from a to z
for(int i = 0; i < 26; i++)
{
// Check if the respective bit is set
if(drives & (1 << i))
{
// ... and if so, print it
_tprintf(TEXT("Drive %c: exists\n"), _T('A') + i);
}
}
return 0;
}
GetLogicalDriveStrings() is the way to go, you just have to use to correctly. You are assuming it returns a single string containing all of the drive strings, but that is not true. It returns an array of strings, one for each drive, so you have to loop through the array instead:
#include <windows.h>
int main()
{
TCHAR buffer[(4*26)+1] = {0};
GetLogicalDriveStrings(sizeof(buffer) / sizeof(TCHAR), buffer);
for (LPTSTR lpDrive = buffer; *lpDrive != 0; lpDrive += 4)
MessageBox(NULL, lpDrive, "Drive in the system", MB_OK);
return 0;
}

Concatenating Two FASTA Files in C++

I have two FASTA files:
file1.fasta
>foo
ATCGGGG
>bar
CCCCCC
file2.fasta
>qux
ATCGGAAA
What I want to do now is to concatenating them into one file that results:
>foo
ATCGGGG
>bar
CCCCCC
>qux
ATCGGAAA
Thus preserving the name of each sequence that started with ">".
Currently my code below replace that name with index, namely:
>0
ATCGGGG
>1
CCCCCC
>0
ATCGGAAA
What's the right way to modify my code below?
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include<stdio.h>
#include<string>
using namespace std;
#define MAX_LINE_SIZE 1024
int mk_joint_file(char *ctrlFile, char *tgtFile, char *outFile){
char s[MAX_LINE_SIZE];
FILE *ofp = fopen(outFile,"w");
FILE *cfp = fopen(ctrlFile,"r");
FILE *tfp = fopen(tgtFile,"r");
// char *p;
int flg=false;
int line=0;
while(fgets(s,MAX_LINE_SIZE,cfp) != NULL){
if(s[0]=='>'){
flg=true;
fprintf(ofp,">%d\n",line);
line++;
}else{
if(flg==true){
fprintf(ofp,"%s",s);
}
flg=false;
}
}
flg=false;
line=0;
while(fgets(s,MAX_LINE_SIZE,tfp) != NULL){
if(s[0]=='>'){
flg=true;
fprintf(ofp,">%d\n",line);
line++;
}else{
if(flg==true)
fprintf(ofp,"%s",s);
flg=false;
}
}
fclose(cfp);
fclose(tfp);
fclose(ofp);
return(0);
}
int main(int argc, char **argv)
{
string ifname_control = argv[1];
string ifname_target = argv[2];
string ofname = "newjoin.txt";
mk_joint_file((char *)ifname_control.c_str(), (char *)ifname_target.c_str(), (char *)ofname.c_str());
}
Is it any harder than just changing these lines
fprintf(ofp,">%d\n",line);
to
// TODO check fgets() handling of EOL - may not need the \n
fprintf(ofp, %s\n", s);
just change line 29 and 40 to
fprintf(ofp,"%s",s);