I would like to read unlimited length line of text from the input. I wish not to use string or any of it.
I tried that but it seems does not work. I always get the same output.
I do not want to use: string, the input has to be of any length.
#include <iostream>
#include <stdio.h>
using namespace std;
char * getline(){
char * buf = new char[10];
int result = scanf("%as\n", &buf);
if (result < 0) {
if (NULL != buf)
delete []buf;
return NULL;
}
return buf;
}
int main(){
char* haha = getline();
cout <<haha << endl;
return 0;
}
char * buf; just creates the pointer variable, but does not allocate memory.
use: buf = new char[...].
Obviously, since your computer has not got unlimited memory, you will need to specify a size instead of ...
And delete it as: delete [] buf
But, I think the best solution is:
std::string s;
std::cin >> s;
You can't read into a buffer that doesn't exist! Here buf points to an undefined location in memory, and the most likely outcome of this code is a crash. You must allocate some space (using new[]) before you can read data into it; and of course, that space must be of some well-defined size. You can always allocate a new, large buffer at any time, and copy the contents of the smaller one into it; this is how you "grow" memory blocks in C++, and it's how string works internally.
Related
I read this sample code in a book. I can't figure out why this part of the following sample code's function declaration is necessary:
while (i <= n)
p[i++] = '\0'; // set rest of string to '\0'
Here is the whole code:
#include <iostream>
const int ArSize = 80;
char * left(const char * str, int n = 1);
int main()
{
using namespace std;
char sample[ArSize];
cout << "Enter a string:\n";
cin.get(sample,ArSize);
char *ps = left(sample, 4);
cout << ps << endl;
delete [] ps; // free old string
ps = left(sample);
cout << ps << endl;
delete [] ps; // free new string
return 0;
}
// This function returns a pointer to a new string
// consisting of the first n characters in the str string.
char * left(const char * str, int n)
{
if(n < 0)
n = 0;
char * p = new char[n+1];
int i;
for (i = 0; i < n && str[i]; i++)
p[i] = str[i]; // copy characters
while (i <= n)
p[i++] = '\0'; // set rest of string to '\0'
return p;
}
I ran the code after I erased it and there was no problem.
The loop is unnecessary. Null-terminated strings end at the first null byte. If more memory was allocated than the actual string needs, it does not matter what’s in those extra bytes. All non-broken C-string handling code stops at the first null terminator. All that’s required is a single
p[i] = '\0';
after the for loop. However, that one null byte is mandatory. C-string functions depend on it and will happily overrun the allocated memory if it’s missing. Essentially they’ll (try to) keep going until they stumble upon the next null byte in memory. If that is past the allocated memory it causes undefined behaviour, resulting in a crash if you’re lucky; or corrupted data if you’re less lucky.
That said: Throw away that book yesterday. The code is a catastrophe from the first to the last line. It barely qualifies as C++. Most of it is plain C. And even as C code it’s highly questionable.
Why to avoid using namespace std. #vol7ron pointed out in the comments that the major complaint is against using namespace std in headers. Here it’s used inside a function in a .cpp file, which lessens the impact significantly. Although in my opinion it is still worth avoiding. If you don’t know the implementation of your standard library in depth, you don’t really have an idea about all the symbols you pull into your scope. If you need it for readability, pulling in specific symbols (e.g. using std::cout;) is a better choice. Also, I’m confident I’m not alone in kind of expecting the std:: prefix. For example, std::string is what I expect to see. string looks slightly off. There’s always a lingering doubt that it might not be the std library string, but a custom string type. So, including the prefix can benefit readability as well.
Why all the C-string pain? We’ve had std::string for a while now …
Copying characters in a loop? Seriously? That’s what std::strcpy() is for.
Raw new and delete everywhere: error prone because you have to keep track of the new/delete pairs manually to avoid memory leaks.
Even worse: asymmetric owning raw pointers. left() allocates and returns a pointer; and it’s the caller’s responsibility to delete it. It doesn’t get more error prone than that.
… And these are only the problems that stick out on first glance.
What that piece of code should look like:
#include <iostream>
#include <string>
std::string left(const std::string& str, std::size_t len = 1);
int main()
{
// getline can fail. If that happens we get an empty string.
std::string sample;
std::getline(std::cin, sample);
auto ps = left(sample, 4);
std::cout << ps << '\n';
ps = left(sample);
std::cout << ps << '\n';
return 0;
}
// `len` may be longer than the string. In that case a copy
// of the complete input string is returned.
std::string left(const std::string& str, std::size_t len)
{
return str.substr(0, len);
}
So here's my code, but I don't know how to make the new file's name the original file's name reversed.
#include
int main(int argc, char *argv[]){
string text;
ifstream orig;
reverse(name[0],name[name.size()]);
orig.open(argv[1], ios::binary);
char *c = new char[1];
if(orig) {
orig.seekg(0, orig.end);
int length = orig.tellg();
orig.seekg(0, orig.beg);
}
while(orig.read(c,1)) text += c;
std::reverse(text.begin(), text.end());
ofstream reverse("copy.dat");
reverse << text;
orig.close();
reverse.close();
return 0;
}
Allocating a single char array instead of just using an automatic array is wasteful, and forgetting to delete it causes a memory leak, but a vanishingly small inefficiency compared to the O(N2) complexity of the main loop.
You should allocate get the filesize, allocate an array of char of said size and read it in one call to read.
I am in need of some help with this program. I am in my first ever programming class and have run into wall trying to getting my program to work. I have included what I have written so far but still it doesn't compile. It is giving the error: argument list for class template "std::vector" is missing.
Here is the question:
When you read a long document, there is a good chance that many words occur multiple times. Instead of storing each word, it may be beneficial to only store unique words, and to represent the document as a vector of pointers to the unique words. Write a program that implements this strategy. Read a word at a time from cin. Keep a vector <char *> of words. If the new word is not present in this vector, allocate memory, copy the word into it, and append a pointer to the new memory. If the word is already present, then append a pointer to the existing word.
Below is code snippet:
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
/* Create a vector of char pointers to hold the individual words.
Create a string input to hold the next input through cin. */
int main() {
vector words;
string input;
/* Keep the while loop running using cin as the condition to read an entire document.
This will end when a document has reached its end. */
while (cin >> input) {
/* For every word read as a string, convert the word into a c-string by allocating
a new character array with the proper size and using c_str and strcpy to copy
an identical c-string into the memory heap. */
char* temp = new char[input.length() + 1];
strcpy(temp, input.c_str());
/* Next, check if the word is already in the words array. Use a boolean variable
that updates if the word is found. Compare words by using the strcmp function;
when they are equal, strcmp equals 0. */
bool already_present = false;
for (int i = 0; i < words.size(); i++) {
if (strcmp(temp, words[i]) == 0) {
already_present = true;
}
}
/* If the word is already present, delete the allocated memory.
Otherwise, push the pointer into the words vector. */
if (already_present) {
delete temp;
} else {
words.push_back(temp);
}
}
}
I hope below code snippet could be helpful:
#include <string>
#include <iostream>
#include <string.h> // String.h for strcmp()
#include <vector> // Vector Header file is added
using namespace std;
int main() {
vector <char *> words; // vector of char *
string input;
while (cin >> input) {
char *temp = new char[input.length() + 1];
strcpy(temp, input.c_str());
bool already_present = false;
for (unsigned int i = 0; i < words.size(); i++) {
if (strcmp(temp, words[i]) == 0) {
already_present = true;
}
}
if (already_present) {
delete temp;
} else {
words.push_back(temp);
}
}
/* Print the desired output */
for(unsigned int i=0; i<words.size(); i++) {
cout << words[i] << endl;
}
return 0;
}
Any doubt, comments most welcome.
EDIT: After reading your comments, I came to the conclusion that you use Microsoft Visual Stdio. See, the reason you were getting warning is that strcpy() is potentially unsafe because it can lead to buffer overflow if you try to copy a string to a buffer that is not large enough to contain it.
Consider a code snippet for a moment:
char foo[10]; /* a buffer able to hold 9 chars (plus the null) */
char bar[] = "A string longer than 9 chars";
strcpy( foo, bar ); /* compiles ok, but VERY BAD because you have a buffer overflow
and are corrupting memory. */
strcpy_s() is safer because you have to explicitly specify the size of the target buffer, so the function will not overflow:
strcpy_s( foo, 10, bar ); /* strcpy_s will not write more than 10 characters */
The limitations of this strcpy_s() is that, it is non-standard and MS specific. Therefore if you write code to use it, your code will not be portable any more.
If it makes sense.
This is how it looks so far.
#include <iostream>
int main()
{
char *buffer;
buffer = new char[100];
std::cin >> buffer;
const int size = strlen(buffer);
char input[size];
delete buffer;
return 0;
}
I know I can use the string library but I'm trying to do without it.
I want to make the char size (in the code char input) depending on the input size.
The errors which I am getting is
expression did not evaluate to a constant
expression must have a constant value
on line 12 which is the
char input[size];
I know I can use the string library but I'm trying to do without it.
You can use std::vector<char>. If that is not an option either, allocate memory yourself and make sure that you deallocate the memory.
char* input = new char[size+1]; // Add an extra for the terminating null characterr
....
delete [] input;
For std::cin you need to pre-allocate a buffer. If you plan on using char[] and you really have to avoid strings you have to make sure you allocate enough memory.
Alternatively you can read char by char with scanf("%c",&newChar) until user inputs an escape character and allocate memory for array as you go.
I don't suppose you're limited to using iostream ?
If it is the length of used space in the buffer array you are trying to assign to size for the input array, there are two methods you can use...
#include <iostream>
using namespace std;
int main()
{
char *buffer = new char[100];
cin >> buffer;
int spaceUsed = 0;
for (unsigned int i = 0; i < 100; i++)
{
if (buffer[i] != '\0')
spaceUsed++;
}
char input[spaceUsed];
delete [] buffer;
return 0;
}
OR...
#include <iostream>
using namespace std;
int main()
{
char *buffer = new char[100];
cin >> buffer;
int spaceUsed = 0;
while (*buffer++)
spaceUsed++;
char input[spaceUsed];
delete [] buffer;
return 0;
}
Both code snippets do the exact same thing. Of course, using the string library would make your life much easier though.
I'm simply trying to read a file using fread and output the contents. It's partially working. It outputs everything correctly but it ends with a bunch of random characters.
#include <iostream>
using namespace std;
void ReadFile(char* filename,char*& buffer)
{
FILE *file = fopen(filename,"rb");
fseek(file,0,SEEK_END);
int size = ftell(file);
rewind(file);
buffer = new char[size];
memset(buffer,0,size);
int r = fread(buffer,1,size,file);
cout << buffer;
fclose(file);
}
int main()
{
char* buffer;
ReadFile("test.txt",buffer);
cin.get();
}
Let's say 'size' is 50 in this instance. for some reason, the size of buffer ends up 55 or 56 after fread is called. I emptied the buffer before using it and tried outputting it, everything is normal (it's empty). Right after the call to fread the buffer somehow gets bigger and is filled with random characters. I've opened the text file in a hex editor to ensure there isn't anything I'm not seeing but there isn't. The file is 50 bytes. fread returns the amount of bytes read, in this case returned to 'r', 'r' is what it should be. so where the mother eff are these bytes coming from?
simplified: fread returns correct amount of bytes read but the buffer somehow makes itself bigger after fread is called, then fills it with random characters. why?
I can't for the life of me figure out how this is happening.
Also, before anyone gives me an easy fix, I already know I could just do buffer[r] = '\0' and not have it output anymore random characters but I'd much rather know WHY this is happening.
cout's << operator on char* expects C strings, so you need to null-terminate your buffer:
int size = ftell(file)+1; // Leave space for null terminator
...
int r = fread(buffer,1,size-1,file);
buffer[r] = '\0';
cout << buffer;
The extra characters that you see is random data in the memory addresses after the end of your buffer. operator << does not know that the string has ended, so it continues printing until it finds the first '\0' byte.
You probably just forgot about null terminating the buffer. Instead, use cout.write and supply the length of the buffer:
Adding a bit of error handling (not enough, but a start), missing includes and using statements: http://coliru.stacked-crooked.com/view?id=8bc4f3b7111554c705de96450d806104-f674c1a6d04c632b71a62362c0ccfc51
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
using namespace std;
void ReadFile(const char* filename,char*& buffer)
{
FILE *file = fopen(filename,"rb");
if (!file)
return;
fseek(file,0,SEEK_END);
int size = ftell(file);
rewind(file);
buffer = new char[size];
memset(buffer,0,size);
int r = fread(buffer,1,size,file);
cout.write(buffer, r);
fclose(file);
}
int main()
{
char* buffer;
ReadFile("test.txt",buffer);
cin.get();
}
Actually cout will print the string until it does not get any NULL char. That mean it needed a NULL for termination.
But assign a NULL is not a good solution for all the times. Your data might be a binary at that time cout will print only the output up to the NULL char. I mean binary data could be anything and it could be a not readable char also. and cout will consider it as a NULL char. That's why it always safe to use a for loop up to the length of the string or your dataset.
len = strlen(buffer)
for (int i = 0; i < len; i++)
printf("%c", buffer[i])
//or you could use FILE *fp; for (int i= 0; i < len; i++) fprintf(fp, "%c", buffer[i]); another good approach is to use fwrite.