Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Is there any way to make the following piece of code shorter? Maybe there is a way to use only one sprintf command, but I don't know how. I need to avoid printing x when its value is zero.
char msg[1000];
string s1 = "s1";
string s2 = "s2";
string s3 = "s3";
int x = 0;
if(x == 0)
sprintf(msg, "%s,%s,%s \n", s1.c_str(), s2.c_str(), s3.c_str());
else
sprintf(msg, "%s,%s,%s,%d \n", s1.c_str(), s2.c_str(), s3.c_str(), x);
Since you're using C++, why not use stringstream to build your buffer in pieces:
#include <cstdio>
#include <sstream>
#include <string>
using namespace std;
int main() {
string s1 = "s1";
string s2 = "s2";
string s3 = "s3";
int x = 0;
stringstream ss;
ss << s1 << "," << s2 << "," << s3;
if (x != 0)
ss << "," << x;
ss << " " << endl;
// Don't do this! See link below
//const char* c = ss.str().c_str();
string result = ss.str();
const char* c = result.c_str();
printf("Result: '%s'\n", c);
getchar();
return 0;
}
Don't let std::stringstream.str().c_str() happen to you
Since the printf family of functions evaluate but ignore any unused arguments, this would be one option;
sprintf(msg, x == 0 ? "%s,%s,%s \n" : "%s,%s,%s,%d \n",
s1.c_str(), s2.c_str(), s3.c_str(), x);
For readability and clarity, I would personally keep your current version though. Until really proven to be a problem, readability trumps micro optimization any day.
Simple, break it out into parts:
printf("%s,%s,%s", s1.c_str(), s2.c_str(), s3.c_str()); // no newline
if(x != 0)
printf(",%d", x);
printf(" \n");
When trying to do things like this, think of it as a math problem: Factor out what's in common between the two statements and do it regardless of the if conditional.
If you want to use sprintf (since you changed your question), you'll need to adjust the pointer into the buffer that you pass each time to account for what's already been written. Also, you should use snprintf which takes a length parameter, to make sure you don't over-run your buffer. This length would need adjusted after each step as well.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 months ago.
Improve this question
Hi everyone I have a simple task in C++:
-> writing a program that takes a string from user input and loops over the characters in the string via a pointer.
If I understand correctly, then a previously declared string name; variable can also be accessed via const char*, implying that I can declare a pointer in the following manner: const char *pName = &(name[0]);. When printing the pointer, however, not the memory address but the actual variable is displayed in the terminal (see my code below). This prevents me from incrementing the pointer (see for loop).
Filename: countchar.cpp
#include <iostream>
using namespace std;
int main() {
string name;
std::cout << "Provide a string." << endl;
std::cin >> name;
const char *pName = &(name[0]);
cout << pName << endl;
// further downstram implementation
// int len = name.length();
// for(int ii = 0; ii < len; ii++){
// std::cout << "iteration" << ii << "address" << pName << endl;
// std::cout << "Character:" << *pName << endl;
// (pName+1);
// }
return 0;
}
Terminal output:
$ g++ countchar.cpp -o count
$ ./count
$ Provide a string.
$ Test
$ Test
As I am a quite a noob in regard to C++ help and an explanation are both highly appreciated (No material found online that solves my problem). Thanks in advance!
The operator << overloaded for a pointer of the type char * such a way that it outputs the string pointed to by the pointer.
So according to the assignment instead of these statements
const char *pName = &(name[0]);
cout << pName << endl;
you need to use a loop like
for ( const char *pName = &name[0]; *pName != '\0'; ++pName )
{
std::cout << *pName;
}
std::cout << '\n';
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 12 months ago.
Improve this question
#include <bits/stdc++.h>
using namespace std;
int main()
{
char *str;
gets(str);
int size = strlen(*(&str));
//How to iterate through this str which is acting like a string here
return 0;
}
//I'm trying to print each char in a new line.
Ignoring all the other problems, such as using an uninitialized pointer, using gets (it's so bad it's been removed from C and C++), including bits/stdc++.h, not using std::string and std::getline...
Using your size variable, you can use loop like this:
for(int index = 0 ; index < size ; ++index) {
std::cout << "character at index " << index << " is '" << str[index] << "'\n";
}
But note that your code will crash at gets and never get to this loop. Please find better learning material to get started with C++!
PS. To get your code to not crash, change char *str; to char str[10000];... Then that program should run and you are unlikely to accidentally cause a buffer overflow. Still, I repeat, get better learning material!
The character pointer str doesn't point to any char object and has not been initialized.
Second, the function gets has been deprecated in C++11 and removed in C++14.
A better way would be to use std::string instead as shown below:
#include <string>
#include <iostream>
int main()
{
std::string str;
//take input from user
std::getline(std::cin, str);
//print out the size of the input string
std::cout << str.size() << std::endl;
//iterate through the input string
for(char& element: str)
{
std::cout<<element<<std::endl;
}
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I have 50 image files which I want to rename.
from: img (1) - Copy.jpg
to: picture_1.jpg
Do you know more elegant way to write it? I came up with this:
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
int main()
{
string oldname = "";
string newname = "";
char oldfilename[20];
char newfilename[30];
for (int i = 1; i <= 50; i++)
{
oldname = "img ("+ to_string(i) +") - copy.jpg"; // old file name
newname = "picture_" + to_string(i) + ".jpg"; // new file name
strcpy(oldfilename, oldname.c_str());
strcpy(newfilename, newname.c_str());
if (rename(oldfilename, newfilename) != 0)
perror("Error renaming file");
else
{
cout << oldfilename << " renamed successfully to " << newfilename << endl;
}
}
char c;
cin >> c;
return 0;
}
This smells like an x y problem. Why are you reaching for C++ to do this?
If you insist on C++ (not to be confused with C), then you should avoid char arrays and strcpy and friends. In particular, strcpy is very dangerous (at least use strncpy, which can't overrun the buffer).
The code can be improved a great deal by making use of C++17 and C++20 features. In particular, formatting the filename can be done with std::format() (or use the {fmt} library if this feature is not supported by your compiler yet):
for (int i = 1; i <= 50; ++i) {
auto oldname = std::format("img ({}) - copy.jpg", i);
auto newname = std::format("picture_{}.jpg", i);
And use C++17's std::fileystem::rename() to rename files without resorting to C functions:
try {
std::filesystem::rename(oldname, newname);
} catch (std::filesystem::filesystem_error &err) {
std::cerr << std::format("Error renaming file: {}\n", err.what());
}
}
If your compiler doesn't support std::filesystem yet, you can use boost::filesystem instead.
I'm going to simplify what the asker had and apply some general best practices. For ease of comparison, I'm sticking to old school C++ code. Comments explaining what I did and why are embedded to keep the explanations close to what they explain.
#include <iostream>
#include <cstdio>
#include <string>
// using namespace std should only be used under controlled circumstances
// if at all.
int main()
{
// removed all variables
for (int i = 1; i <= 50; i++)
{
// Keep variable definitions close to usage unless you have a good
// reason not to. Can't think of any good reasons.
std::string oldname = "img ("+ std::to_string(i) +") - copy.jpg";
std::string newname = "picture_" + std::to_string(i) + ".jpg";
// no need for the char arrays or the strcpys. Instead we will use the
// std::string::c_str function to get the string's backing array
// If C++17 or newer is available we could use std::filesystem::rename.
// I'm leaving off the std:: prefix on rename because C is all we need
if (rename(oldname.c_str(), newname.c_str()) != 0)
{ // I find that always using the optional braces prevents future bugs.
// That's a personal opinion and choice.
perror("Error renaming file");
}
else
{
std::cout << oldname << " renamed successfully to " << newname << std::endl;
}
}
char c;
std::cin >> std::noskipws >> c; // >> c will ignore whitespace, so the user
// cannot advance simply by pressing enter.
return 0;
}
A note on comments. If the purpose of the code cannot be inferred from the code and the variable names, consider changing the code. Only comment the stuff that's still arcane no matter how you rework it.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
Hello i'm from Indonesia. and i'm verry beginner on C++ programming. I have some problem when i learn about string on C++ . First i declared array of char and i want to initialize a value separately in different command. After i initialize the value my compiler say "Invalid Argument".
#include <iostream>
using namespace std;
int main() {
char Name[5];
Name = "Luke";
cout<<"Character 0 :"<<Name[0]<<endl;
cout<<"Character 1 :"<<Name[1]<<endl;
cout<<"Character 2 :"<<Name[2]<<endl;
cout<<"Character 3 :"<<Name[3]<<endl;
cout<<"Character 4 :"<<Name[4]<<endl;
return 0;
}
sorry if my english is bad :(
A character array(including a C string) can not have a new value assigned to it after it is declared.
The C++compiler interprets these assignment statements as attempts to change the address stored in the array name, not as attempts to change the contents of the array.
However you can use
char name[] = "Luke";
A char[] can't be assigned with a string with the = operator, except for on its initialization. That's why char Name[5]; Name = "Luke"; is invalid while char Name[5] = "Luke"; is.
Assigning strings to char[] can be done with strcpy() / memcpy()-like functions.
So you have two ways of action (assuming you want to work with char[]):
char Name[5] = "Luke";
char Name[5]; strcpy(Name, "Luke"); /* don't forget to #include <string.h>*/
Just for sake of education (since the other answers are on-point to answer the question), here's how I would have written your code to do nearly the same thing.
The changes demonstrate:
used a more appropriate container (a string instead of a char[])
checked for access overruns
moved "one unit of work" into its own subroutine
Code was compiled as C++17 with /usr/bin/clang++ -Weverything -Wno-c++98-compat --std=c++1z:
#include <cstddef>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
void PrintCharAtPos(string const& s, string::size_type pos);
int main() {
auto Name = string{"Luke"};
PrintCharAtPos(Name, 0);
PrintCharAtPos(Name, 1);
PrintCharAtPos(Name, 2);
PrintCharAtPos(Name, 3);
PrintCharAtPos(Name, 4);
return EXIT_SUCCESS;
}
void PrintCharAtPos(string const& s, string::size_type pos) {
if (pos < s.length())
cout << "Character " << pos << " : " << s[pos] << endl;
else
cout << "Character " << pos << " : (out of bounds)" << endl;
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
so i need to read in a file, then create a word count and a character count for each time the character appears using an array. each word ends with whitespace, comma, period, etc. also i need to put a tolower and an equation to set the letters to the right array with an x-'a' function or something like that.
list of errors from puTTy(crappy program i know but it's required)
project8.cpp: In function âint main()â:
project8.cpp:17: error: âfile1â was not declared in this scope
project8.cpp:18: error: expected â;â before âwhileâ
project8.cpp:36: error: expected â}â at end of input
#include <iostream>
#include <string>
using namespace std;
int in_word = false;
int word_count = 0;
char ch;
char low_case;
int char_count[26];
int i;
int main()
{
for (i=0; i<26; i++)
char_count[i]=0;
cin.get(file1.txt)
while('\n' !=(ch=cin.get(file1.txt)))
{
if (' ' == ch || '\n' == ch || '\t' == ch)
in_word = false;
else if (in_word == false)
{
in_word=true;
word_count++;
}
else low_case=tolower(ch);
char_count[int(low_case)-int('a')]++;
}
cout << file1.txt;
cout << words << " words" << endl;
for (i=0; i<26; i++)
if(count[i] !=0)
cout << count[i] << " " << char(i+'a') << endl;
}
The first problem is that you haven't declared file1. It is somewhat unclear what file1.txt really is meant to be: The way it is written, it seems to be an object of type with a member called, txt of type char* or char[N] (with a constant N). From the looks of it, you actually wanted to open a file named file1.txt. This would look like so:
std::ifstream in("file1.txt");
After that you would, of course, use in instead of std::cin to read from the file. For example you could use
for (char c; in.get(c); ) {
// ...
}
to read each individual character of the file and process it appropriately.
Let's play compiler!
You cannot name a variable file1.txt, call it file1
Also, you forgot the semi-colon ; at the end of the line, so
cin.get(file1.txt)
should be
cin.get(file1);
I don't quite know where you are defining this variable, so you may be missing a declaration like
const char* file1="file1.txt";
Furthermore, you start trying to access some variable count after your for-loop here:
count[i]
Did you mean to use char_count?