For an assignment I have written two programs.
One for generating a file of random integers, the other for counting integers less than a specified threshold.
You can find the actual assignment texts below the code I've posted.
When compiling g++ generate.cpp -o generate, I get this error:
z1755294#hopper:~/assign2$ g++ generate.cpp -o generate
generate.cpp: In function ‘bool writeRand(int, int, int, const char*)’:
generate.cpp:12:31: error: variable ‘std::ofstream fout’ has initializer but incomplete type
ofstream fout ( fname );
When I compile g++ thresh.cpp -o thresh, I get this error:
z1755294#hopper:~/assign2$ g++ thresh.cpp -o thresh
thresh.cpp: In function ‘int main()’:
thresh.cpp:19:16: error: variable ‘std::ifstream fin’ has initializer but incomplete type
ifstream fin( fname.c_str() );
Can anyone help me fix my code to get it working? Also I need to create a Makefile for my project since I have multiple executables?
Thanks so much...kinda stuck on what to do.
This is my code:
generate.cpp
#include <iostream>
#include <cstdlib> // re. atoi
using std::cout;
using std::endl;
using std::cerr;
using std::ifstream;
using std::ofstream;
bool writeRand ( const int ranSeed, const int maxVal, const int numVals, const char* fname )
{
ofstream fout ( fname );
if ( fout )
{
srand ( ranSeed );
for ( int i=0; i < numVals; ++ i )
fout << rand () % (maxVal+1) << endl;
fout.close ();
return true;
}
//else
return false;
}
int main ( int argc, char* argv [] )
{
if (argc !=5 )
{
cerr << "Usage: " << argv[0] << "ranSeed maxVal numVals outFileName" << endl;
return -1;
}
const int ranSeed = atoi(argv[1]);
const int maxVal = atoi(argv[2]);
const int numVals = atoi(argv[3]);
const char* fname = argv[4];
if ( ranSeed <= 0 || maxVal <= 0 || numVals <= 0 )
{
cerr << "Invalid negative or zero numbers on command line....Try again..." << endl;
return -1;
}
if ( writeRand( ranSeed, maxVal, numVals, fname ) )
cout << "ranSeed = " << ranSeed << ", maxVal = " << maxVal << ", numVals = " << numVals
<< "\nfame " << fname << " was created ok ..." << endl;
else
cout << "There was a problem creating file " << fname << " ..." << endl;
}
thresh.cpp
#include <iostream>
#include <cstdlib> // re. atoi
using std::cout;
using std::endl;
using std::cin;
using std::ifstream;
using std::string;
using std::flush;
int main ()
{
//prompt and take in the desired file name
cout << "Enter name of file (for example randNums.txt): " << flush;
string fname;
getline( cin, fname );
//then can open file
ifstream fin( fname.c_str() );
if( fin )
{
int max, count = 0, below = 0, val = 0;
string line;
while( true )
{
cout << "Enter the threshold value: " << flush;
getline( cin,line );
max = atoi( line.c_str() );
if( max > 0 ) break;
cout << "Try again with value > 0 \n";
}
while( getline( fin, line) )
{
val = atoi( line.c_str() );
++count;
if( val < max ) ++below;
}
fin.close();
cout << below << " of " << count << " values in file '"
<< fname << "' are less than " << max << '\n';
max = val+1; //last value (in file) + 1
count = 0, below = 0;
fin.open( fname.c_str() );
while( getline( fin, line ) )
{
int val = atoi( line.c_str() );
++count;
if( val < max ) ++below;
}
fin.close();
cout << below << " of " << count << " values in file '"
<< fname << "' are less than " << max << '\n';
}
else
cout << "There was an error opening file " << fname << '\n';
cout << "Please 'Enter' to continue/exit..." << flush;
cin.get();
return 0;
}
Assignments
generate
Create a program called "generate" which generates a file of random integers.
This program takes four command line arguments. They are, in order
*A random number seed. This is an integer value explained below.
*A maximum value. The random values should be less than this maximum. This value is an integer.
*The number of values to be generated
*The name of an output file to store the values
If the command line arguments are not given, the program should give a brief message on proper usage and then exit. The integer values on the comand line should all be checked for negative values. If a negative value is given, the program should print an error message and exit.
Random number generation
The rand() function, found in returns a random positive integer every time it is called. The srand(int) function takes an integer called the random number seed which is used to initialize the random number generator. Subsequent calls to rand() produce a random sequence which is uniquely tied to its seed. Typically in a program, srand() is called once, while rand() is called multiple times.
A common technique for producing random numbers of a particular size is to use the remainder of divding rand() by the maximum upper bound.
thresh
Create a program called thresh which should ask the user for a file name and an integer threshold value. The program should then count the number of values in the file less than the threshold and report the results.
For example, 43 of 300 values in mydatafile are less than 17
This program should not use command line arguments. Rather, needed values should be obtained by prompting the user.
When asking for the threshold value, if the user inputs a negative value, the program should print an error and loop on the request until a proper value is obtained.
If the input file does not exist, an error message should be printed and the program should exit.
Hints:
Test your programs with small values that can be checked by hand. For example, create a file of 20 values less than 10. A particularly good test of thresh is to use the last value of the data file as a threshold value. Then use the last value plus one as a threshold value.
**A Makefile is required as part of your submission. If the project has multiple executables, you should have a default makefile rule to build all of the executables. You should have a rule to clear out the project to a pristine state. Your Makefile should use appropriate variables.
As #mrunion pointed out, you should replace
g++ generate.cpp thresh.cpp
with g++ generate.cpp
and g++ thresh.cpp
By the way, if you do these back to back, you'll overwrite your executable. An improvement would be:
g++ generate.cpp -o generate
and
g++ thresh.cpp -o thresh
Related
I wanna compare value that stored in filename[i] and filename[j] and print out the value in filename[i] that do not have the same filename as in filename[j]. I know it is possible to do using set_difference and sort solution but I do not know exactly to write the sort and set_differences code. Here i provide my original code so that u can test it out and more understand what I'm trying to do.
my full code:
#include <string>
#include <iostream>
#include <ctime> //important when to make random filename- srand(time(0))
#include <opencv2\opencv.hpp> //important when using opencv
#include <vector> //when using vector function
using namespace std;
using namespace cv; //important when using opencv
int main(int argc, char* argv[]) {
vector<String> filenames;
int a, i;
srand(time(0)); //seed random filenames - for random filename
// Get all jpg in the folder
cv::glob("C:\\Users\\x\\Documents\\Aggressive\\abc", filenames);
for (size_t i = 0; i < filenames.size(); i++)
{
Mat im = imread(filenames[i]); //read the filename location
std::cout << "\n";
std::size_t found = filenames[i].find_last_of("//\\");
//std:cout << " file: " << filenames[j].substr(found + 1) << '\n'; //display filename and its format (.jpg)
std::string::size_type const p(filenames[i].substr(found + 1).find_last_of('.')); //eg: 2.jpg then it will find the last '.'
std::string file_without_extension = filenames[i].substr(found + 1).substr(0, p); //eg: 2
std::cout << " file : " << filenames[i].substr(found + 1).substr(0, p); //display filename without .jpg
}
cout << "\n";
cout << "There's " << filenames.size() << " files in the current directory.\n" << endl; // total file in the specific directory
cout << "Enter array size: \n";
cin >> a;
for (int j = 0; j < filenames.size(); j++) {
//generate random filename
int index = rand() % filenames.size(); //random based on total of the file in the directory
//cout << filenames[index] << endl; //display the random number but might be redundant
//swap filenames[j] with filenames[index]
string temp = filenames[j];
filenames[j] = filenames[index];
filenames[index] = temp;
}
for (int j = 0; j < a; j++) {
//cout << "Random image selected:" << filenames[j] << endl; //basically to avoid the redundant random filename
Mat im = imread(filenames[j]); //read filename location
std::size_t found = filenames[j].find_last_of("//\\");
//std:cout << " file: " << filenames[j].substr(found + 1) << '\n'; //display filename and its format (.jpg)
std::string::size_type const p(filenames[j].substr(found + 1).find_last_of('.')); //eg: 2.jpg then it will find the last '.'
std::string file_without_extension = filenames[j].substr(found + 1).substr(0, p); //eg: 2
std::cout << " file: " << filenames[j].substr(found + 1).substr(0, p); //display filename without .jpg
string written_directory = "C:/Users/x/Documents/folder/" + filenames[j].substr(found + 1).substr(0, p) + ".jpg"; // write filename based on its original filename.
imwrite(written_directory, im);
}
return 0;
}
In my opinion this is a perfect example of an XY Problem. From you question, from your code and even from the comments, people do not really understand what you want to do. With that I mean, what do you want to achieve?
It is a vague guess that you want to copy a specified number of random selected JPEG files from one directory to the other. And that you want to show the filenames of the files that will not be copied.
Let me give you some examples, what is the reason for all this confusion.
First and most important, you do not show the full code. Definitions and variable types and functions are misssing an. This is also not a Minimum, Reproducable Example. And the description in your question is hard to understand.
I have two set of array
You have "two set array"? Do you mean, you have 2 [std::set][3] of [std::array][3]. Or maybe you have simply 2 [std::vector][3] of std::string. From what we can see in the code, we could assume a std::vector<std::string>>, but we do not know, because you did not show the feinition of "filenames".
Then, you are talking about "2" something. But we do see only one "filenames". So, 2 or 1?
in a comment you are writing
in the array 2 i had a random filename based on the size of array that an user entered
My guess is that you do not want to have a random filename, but you want to select filenames with a random index from the first vector and put it into a 2nd vector? But we can see only 1 vector "filenames" where you do some random swapping activity.
Then you have written
imread is actually to read the whole file in the folder of directory
This function is very important, what does it do? And what do you mean by "read the file"? Do you mean "filename", so the name of the file? Or the contents of the file? And what is the meaning of "folder of directory"? All filenames in one folder? Or subfolder of a directory entry?
So now my objective is to print out all the file that do not have same filename in the array 2
Again, do we really have 2 arrays(vector)? are they different?
And then, where do you copy the files?
So, you see, it is very hard to understand. Even, if people would like to help you, they cannot, because they do not understand you. Better to show a link to your original home work. Then people can help you. Members here on Stack Overflow want to help. But please allow them to do so.
Here I give you an abstract example for the random selection problem and set_difference problem:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <random>
int main() {
// Define 2 Vectors for filenames
// This vector is an example for files that could be in a specified directory
std::vector<std::string> fileNamesInDirectory{"8.jpg","5.jpg", "6.jpg", "9.jpg", "1.jpg", "4.jpg", "2.jpg", "3.jpg", };
// Print the filenames as information for the user
for (size_t i = 0U; i < fileNamesInDirectory.size(); ++i) {
std::cout << fileNamesInDirectory[i] << "\n";
}
// Next: Select randomly a given number of filenames from the above vector
// So, first get the number of selections. Inform the user
std::cout << "\nEnter a number of filenames that should be copied randomly. Range: 1-"<< fileNamesInDirectory.size()-1 << "\t";
size_t numberOfSelectedFileNames{};
std::cin >> numberOfSelectedFileNames;
// Check for valid range
if (numberOfSelectedFileNames == 0 || numberOfSelectedFileNames >= fileNamesInDirectory.size()) {
std::cerr << "\n*** Error. Wrong input '" << numberOfSelectedFileNames << "'\n";
}
else {
// Copy all data from fileNamesInDirectory
std::vector<std::string> selection{ fileNamesInDirectory };
// Shuffle the data randomly: Please see here: https://en.cppreference.com/w/cpp/algorithm/random_shuffle
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(selection.begin(), selection.end(), g);
// Resize to the number, given by the user
selection.resize(numberOfSelectedFileNames);
// Now we have a random list of filenames
// Show, what we have so far. Now, because we are learning, we will use the range based for
std::cout << "\n\nOriginal file names:\n";
for (const std::string& s : fileNamesInDirectory) std::cout << s << "\n";
std::cout << "\n\nRandomly selected file names:\n";
for (const std::string& s : selection) std::cout << s << "\n";
// Sort both vectors
std::sort(fileNamesInDirectory.begin(), fileNamesInDirectory.end());
std::sort(selection.begin(), selection.end());
// Show again to the user:3
std::cout << "\n\nOriginal file names sorted:\n";
for (const std::string& s : fileNamesInDirectory) std::cout << s << "\n";
std::cout << "\n\nRandomly selected file names sorted:\n";
for (const std::string& s : selection) std::cout << s << "\n";
// Now, find out the difference of both vectors, meaning, what will not be selected and later copied
std::vector<std::string> difference{};
// Calculate the difference with a std::algorithm: https://en.cppreference.com/w/cpp/algorithm/set_difference
std::set_difference(fileNamesInDirectory.begin(), fileNamesInDirectory.end(), selection.begin(), selection.end(), std::back_inserter(difference));
std::cout << "\n\nThe following file names have not been selected:\n";
for (const std::string& s : difference) std::cout << s << "\n";
}
return 0;
}
If you are more advanced then you can and will use functions from the C++ filesystem library. That will make life easier . . .
I am looking to find a C++ fstream equivalent function of C fgets. I tried with get function of fstream but did not get what I wanted. The get function does not extract the delim character whereas the fgets function used to extract it. So, I wrote a code to insert this delim character from my code itself. But it is giving strange behaviour. Please see my sample code below;
#include <stdio.h>
#include <fstream>
#include <iostream>
int main(int argc, char **argv)
{
char str[256];
int len = 10;
std::cout << "Using C fgets function" << std::endl;
FILE * file = fopen("C:\\cpp\\write.txt", "r");
if(file == NULL){
std::cout << " Error opening file" << std::endl;
}
int count = 0;
while(!feof(file)){
char *result = fgets(str, len, file);
std::cout << result << std::endl ;
count++;
}
std::cout << "\nCount = " << count << std::endl;
fclose(file);
std::fstream fp("C:\\cpp\\write.txt", std::ios_base::in);
int iter_count = 0;
while(!fp.eof() && iter_count < 10){
fp.get(str, len,'\n');
int count = fp.gcount();
std::cout << "\nCurrent Count = " << count << std::endl;
if(count == 0){
//only new line character encountered
//adding newline character
str[1] = '\0';
str[0] = '\n';
fp.ignore(1, '\n');
//std::cout << fp.get(); //ignore new line character from stream
}
else if(count != (len -1) ){
//adding newline character
str[count + 1] = '\0';
str[count ] = '\n';
//std::cout << fp.get(); //ignore new line character from stream
fp.ignore(1, '\n');
//std::cout << "Adding new line \n";
}
std::cout << str << std::endl;
std::cout << " Stream State : Good: " << fp.good() << " Fail: " << fp.fail() << std::endl;
iter_count++;
}
std::cout << "\nCount = " << iter_count << std::endl;
fp.close();
return 0;
}
The txt file that I am using is write.txt with following content:
This is a new lines.
Now writing second
line
DONE
If you observe my program, I am using fgets function first and then using the get function on same file. In case of get function, the stream state goes bad.
Can anyone please point me out what is going wrong here?
UPDATED: I am now posting a simplest code which does not work at my end. If I dont care about the delim character for now and just read the entire file 10 characters at a time using getline:
void read_file_getline_no_insert(){
char str[256];
int len =10;
std::cout << "\nREAD_GETLINE_NO_INSERT FUNCITON\n" << std::endl;
std::fstream fp("C:\\cpp\\write.txt", std::ios_base::in);
int iter_count = 0;
while(!fp.eof() && iter_count < 10){
fp.getline(str, len,'\n');
int count = fp.gcount();
std::cout << "\nCurrent Count = " << count << std::endl;
std::cout << str << std::endl;
std::cout << " Stream State : Good: " << fp.good() << " Fail: " << fp.fail() << std::endl;
iter_count++;
}
std::cout << "\nCount = " << iter_count << std::endl;
fp.close();
}
int main(int argc, char **argv)
{
read_file_getline_no_insert();
return 0;
}
If wee see the output of above code:
READ_GETLINE_NO_INSERT FUNCITON
Current Count = 9
This is a
Stream State : Good: 0 Fail: 1
Current Count = 0
Stream State : Good: 0 Fail: 1
You would see that the state of stream goes Bad and the fail bit is set. I am unable to understand this behavior.
Rgds
Sapan
std::getline() will read a string from a stream, until it encounters a delimiter (newline by default).
Unlike fgets(), std::getline() discards the delimiter. But, also unlike fgets(), it will read the whole line (available memory permitting) since it works with a std::string rather than a char *. That makes it somewhat easier to use in practice.
All types derived from std::istream (which is the base class for all input streams) also have a member function called getline() which works a little more like fgets() - accepting a char * and a buffer size. It still discards the delimiter though.
The C++-specific options are overloaded functions (i.e. available in more than one version) so you need to read documentation to decide which one is appropriate to your needs.
I have encountered the typical No Entry Point Personality V0 error before and worked around it with: -fno-exceptions. Although this time when I use the workaround cmd crashed and only runs the first cin >> line of the program.
However, I can run the program no problem in MSYS.
I compiled with:
g++ ReturnPointer.cpp -o ReturnPointer.exe (gave error)
g++ ReturnPointer.cpp -o ReturnPointer.exe -fno-exceptions (runs: MSYS Shell Only)
#include <iostream>
short factor(int, int*, int*);
int main()
{
int number, squared, cubed;
short error;
std::cout << "Enter a number (0 - 20 ): ";
std::cin >> number;
error = factor(number, &squared, &cubed);
if (!error)
{
std::cout << "number: " << number << "\n";
std::cout << "square: " << squared << "\n";
std::cout << "cubed: " << cubed << "\n";
}
else
std::cout << "Error encountered!!\n";
return 0;
}
short factor(int n, int* pSquared, int* pCubed)
{
short value = 0;
if (n > 20)
{
value = 1;
}
else
{
*pSquared = n * n;
*pCubed = n * n * n;
value = 0;
}
return value;
}
Granted, this isn't the end of the world. I am just expanding my knowledge on an area of C++ that trips me up a lot. Although, if I were to ever use pointers in this manner in a larger program...that would turn into a mess.
I would just like to know what needs to be done or what I am missing to run this in CMD.
Trying to add command line arguments to my programs. So I was experimenting and cannot figure out this intellisense warning for the life of me. It keeps on saying it is expecting a ')', but I have no idea why.
Here is the code it does not like:
// Calculate average
average = sum / ( argc – 1 );
Then it underlines the subtraction operator. Below is the full program.
#include <iostream>
int main( int argc, char *argv[] )
{
float average;
int sum = 0;
// Valid number of arguments?
if ( argc > 1 )
{
// Loop through arguments ignoring the first which is
// the name and path of this program
for ( int i = 1; i < argc; i++ )
{
// Convert cString to int
sum += atoi( argv[i] );
}
// Calculate average
average = sum / ( argc – 1 );
std::cout << "\nSum: " << sum << '\n'
<< "Average: " << average << std::endl;
}
else
{
// If invalid number of arguments, display error message
// and usage syntax
std::cout << "Error: No arguments\n"
<< "Syntax: command_line [space delimted numbers]"
<< std::endl;
}
return 0;
}
The character you think is a minus sign is something else, so it is not parsed as a subtraction operator.
Your version:
average = sum / ( argc – 1 );
Correct version (cut and paste into your code):
average = sum / ( argc - 1 );
Note that calculating an average using integers might not be the best way to do it. You have integer arithmetic on the RHS, which you then assign to float on the LHS. You should perform the division using floating point types. Example:
#include <iostream>
int main()
{
std::cout << float((3)/5) << "\n"; // int division to FP: prints 0!
std::cout << float(3)/5 << "\n"; // FP division: prints 0.6
}
I tried to compile your code on my machine with g++ 4.6.3 and got the follow error:
pedro#RovesTwo:~$ g++ teste.cpp -o teste
teste.cpp:20:8: erro: stray ‘\342’ in program
teste.cpp:20:8: erro: stray ‘\200’ in program
teste.cpp:20:8: erro: stray ‘\223’ in program
teste.cpp: Na função ‘int main(int, char**)’:
teste.cpp:16:33: erro: ‘atoi’ was not declared in this scope
teste.cpp:20:35: erro: expected ‘)’ before numeric constant
Looks like there is some strange char in that line. Remove and re-write the line fixed the error.
I'm using swig to wrap around this C++ project and after having imported all the header files into my python code, I'm now working on re-creating the main class in python, but I'm having trouble looking for the corresponding data structures and data types.
Following is the main method under main.cpp
int main( int argc, char *argv[] )
{
string exe_name = argv[ 0 ];
string usage = "Usage: " + exe_name + " unigene.fasta [options]\n\
Options:\n\
-g <GC content> \tminimum GC content in percentage (Default 45).\n\
-G <GC content> \tmaximum GC content in percentage (Default 55).\n\
-m <temperature> \tlowest melting temperature in degrees of celsius (Default 0).\n\
-M <temperature> \thighest melting temperature in degrees of celsius (Default 100).\n\
-r <repeat.fasta> \tfasta file containing repeat DNA sequences.\n\
-t <top number> \tnumber of top oligos selected for each unigene (Default 1).\n\n";
string unigene_file;
// options only, each must have an associated value
int min_gc = 45;
int max_gc = 55;
int min_tm = 0;
int max_tm = 100;
int top_num = 1;
string repeat_file;
vector< string > m_argument;
for ( int i = 0; i < argc; i ++ ) {
string new_arg = argv[ i ];
m_argument.push_back( new_arg );
}
parse_argument( m_argument, usage, unigene_file,
min_gc, max_gc, min_tm, max_tm, top_num, repeat_file );
// initialize filtration parameters
float norm_min_gc = (float)min_gc / 100.0;
float norm_max_gc = (float)max_gc / 100.0;
string splice_file; // empty splice file
filt_param m_filtparam( norm_min_gc, norm_max_gc, min_tm, max_tm,
repeat_file, splice_file );
// screen unigenes for unique oligos
seqs m_unigene;
m_unigene.init( unigene_file );
// map from unigene names to oligo sequences
map< string, vector< string > > uniq_oligo;
get_unique_oligo( m_unigene, m_filtparam, top_num, uniq_oligo );
// output oligos
if ( uniq_oligo.empty() ) {
cout << "No valid oligo has been found. " << endl <<
"It could be due to one of the following reasons: " << endl <<
"1. input sequences are not unique, or " << endl <<
"2. they are repetitive DNAs, or " << endl <<
"3. GC% range is too restricted, etc. " << endl;
}
map< string, vector< string > > :: const_iterator m_itr;
for ( m_itr = uniq_oligo.begin(); m_itr != uniq_oligo.end(); m_itr ++ ) {
for ( int o_idx = 0; o_idx < (int)m_itr->second.size(); o_idx ++ ) {
cout << ">unique-oligo-" << o_idx+1 << "-of-unigene-" <<
m_itr->first << endl;
cout << m_itr->second[ o_idx ] << endl;
}
}
//system("PAUSE");
return 1;
}
For instance when I try passing an empty string (repeat_file) into filtparam() as done above, in python, I get the error
in method 'new_filt_param', argument 5 of type 'string const &'
How does one declare a 'string const &' type in python?
Also is there a structure like 'map' in python?
What you're looking for is the dict, which essentially works similar to C++'s map. More information can be found in the documentation.
Different question: Is there any reason you're recreating main() in Python rather than simply wrapping that one with SWIG? While SWIG is able to handle things like std::string in a limited way, I'd try to use a more simple interface using pointers/arrays only, rather than trying to pass any C++ objects or constructs.