getline and wchar_t

Hi,
I have the following problem: I want user to write the filename in console.
I tried this:

1
2
3
4
5
6
7
8
#include "stdafx.h"
#include <iostream>
using namespace std;
  int wmain(int argc, wchar_t* argv[])
{
	std::cout << "Enter the filename with extension \n";
	cin.getline(argv[1]);
}


And I get error in the line with "getline":
Error C2661 'std::basic_istream<char,std::char_traits<char>>::getline': no overloaded function takes 1 arguments.

Does anyone know how to fix it?
1
2
3
4
5
#include <string>
...
	std::cout << "Enter the filename with extension \n";
        std::string fname;
        std::getline(std::cin, fname);


Although you could make your original program compile by replacing cin with wcin and passing the second argument, it would not be a good idea because it was writing into argv[1] (while technically correct, it wasn't taking precautions not to exceed its length), it used member getline for no good reason, and it attempted wide character input on Windows without the necessary setup for it.
Last edited on
argv is used for command line arguments sent when the program was started.
You can read from it to retrieve the command line arguments sent.
Do not try to write to it. Ever.

You need to declare some other container to hold the user's input, like a string.

1
2
3
4
5
6
7
8
9
10
11
#include <string>
#include <iostream>

int main(int argc, char* argv[])
{
 std::string input;
 std::cout << "Input: ";
 std::getline(std::cin, input);
 std::cout << "You entered: " << input << std::endl;
 return 0;
}
Well, I need the possibility to choose, which file I want to use. And this is connected with argv[1] (input filename) and argv[2] (output filename).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
int wmain(int argc, wchar_t* argv[])
{

	std::cout << "Enter the filename with extension \n";
	std::getline(std::cin, argv[1]);
	if (argc != 3)
	{
		printf("arguments: input_file output_file.wav\n");
		system("PAUSE");
		return 1;
	}
	
	const WCHAR *wszSourceFile = argv[1];
	const WCHAR *wszTargetFile = argv[2];

	const LONG MAX_AUDIO_DURATION_MSEC = 500000; // 500 seconds = 8 minutes 20 seconds

	HRESULT hr = S_OK;

	IMFSourceReader *pReader = NULL;
	HANDLE hFile = INVALID_HANDLE_VALUE;

	// Initialize the COM library.
	hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

	// Initialize the Media Foundation platform.
	if (SUCCEEDED(hr))
	{
		hr = MFStartup(MF_VERSION);
	}
	
	// Create the source reader to read the input file.
	if (SUCCEEDED(hr))
	{
		hr = MFCreateSourceReaderFromURL(wszSourceFile, NULL, &pReader);
		if (FAILED(hr))
		{
			printf("Error opening input file: %S 0x%08lx\n", wszSourceFile, hr);
			system("PAUSE");
		}
	}

	// Open the output file for writing.
	if (SUCCEEDED(hr))
	{
		hFile = CreateFile(wszTargetFile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
			CREATE_ALWAYS, 0, NULL);

		if (hFile == INVALID_HANDLE_VALUE)
		{
			hr = HRESULT_FROM_WIN32(GetLastError());
			printf("Cannot create output file: %S 0x%08lx\n", wszTargetFile, hr);
			system("PAUSE");
		}
	}

	// Write the WAVE file.
	if (SUCCEEDED(hr))
	{
		hr = WriteWaveFile(pReader, hFile, MAX_AUDIO_DURATION_MSEC);
	}

	if (FAILED(hr))
	{
		printf("Failed, hr = 0x%X\n", hr);
		system("PAUSE");
	}

	// Clean up.
	if (hFile != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hFile);
	}
	
	SafeRelease(&pReader);
	MFShutdown();
	CoUninitialize();
	system("PAUSE");
	return SUCCEEDED(hr) ? 0 : 1;
};


How should I do that, if I shoud not write to argv?
I think I may have misinterpreted the question. The file name is a command line argument?

If so, then read it with argv[1], but you do not need to call getline for that.

If not, then retrieve it similar to how I showed above.
If file has name with space character (I want to open audio files) then how can I read filename without using getline?
And I still get errors using this
std::getline(std::wcin,argv[1]);
Like I said, do not write to argv. It is already filled with whatever arguments were provided when the program was executed (with argv[0] being the command used to invoke the program).

You can see how many arguments were provided by looking at the value of argc. This will always be at least 1 (since argv[0] will be the first argument).

1
2
3
4
for (int i = 0; i < argc; i++)
{
    std::cout << "Argument #" << i << ": " << argv[i] << std::endl;
}


If you need spaces in the file names, I recommend not trying to provide those in command line arguments, as those are delimited by whitespace characters.

Is there a particular reason why you need them as command line arguments? If the user is to manually enter them after the program has started, they won't be command line arguments.

If you need to get input from the user, store it in a string, like std::string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <string>
#include <iostream>

int main(int argc, char **argv)
{
	for (int i = 0; i < argc; i++)
	{
		std::cout << "Argument #" << i << ": " << argv[i] << std::endl;
	}

	std::string input_file, output_file;

	std::cout << "Enter name of input file: ";
	std::getline(std::cin, input_file);

	std::cout << "Reading from file: \"" << input_file << "\"" << std::endl;

	std::cout << "Enter name of output file: ";
	std::getline(std::cin, output_file);

	std::cout << "Writing to file: " << output_file << "\"" << std::endl;
}


Produced this:
Argument #0: C:<some_arbitrary_path>CPPHelp.exe
Enter name of input file: File to read from
Reading from file: "File to read from"
Enter name of output file: File to write to
Writing to file: File to write to"
Press any key to continue . . .


If you must retrieve the information from the command line, you can just read it by referencing argv[i], but do not write to it. You can pass it as a parameter to the string constructor if you wish to put it into a string std::string str(argv[i]) just do not do that unless you know that argv actually contains that (like do not read argv[3] if only 3 arguments were provided, since you'd need 4 arguments to have argv[3]).

There is no reason to use printf or scanf from what I can see, just use std::cout and std::cin, respectively (unless, of course, performance is absolutely critical).
I also don't know why you're using system("PAUSE"), but you probably shouldn't. There are plenty of other ways to make your program wait for something.
If file has name with space character (I want to open audio files) then how can I read filename without using getline?
You can't read command line arguments using any iostream function. Those functions are not designed to do that.
If you need to pass a string with spaces as a single argument, you'll need to add quotes:
some_program "argument with spaces"
Last edited on
I use ready program from this site
https://msdn.microsoft.com/en-us/library/windows/desktop/dd757929(v=vs.85).aspx

This is why printf or scanf are used - I didn't put them. I wrote system("PAUSE") just to know what is going on with my program (It was closing immediately after start).

In earlier post there is (13 and 14 lines)
1
2
const WCHAR *wszSourceFile = argv[1];
const WCHAR *wszTargetFile = argv[2];

wszSourceFile and wszTargetFile are used in functions, so if I can't write to argv after starting the program, is there a possibility to write string to these WCHAR pointers? Something like
1
2
3
4
std::string input_file;
std::cout  << "Enter name of input file: ";
std::getline(std::cin, input_file);
WCHAR* wszSourceFile = input_file      // <-- I know it can't work like that 
You already did.

1
2
const WCHAR *wszSourceFile = argv[1];
const WCHAR *wszTargetFile = argv[2];


Are you providing command line arguments when you start the program like the code you linked to is expecting you to?
Thank you, it's working now by command line.

But isn't there a possibility to make simple changes just to open the program and then write a filenames?
Do you mean by asking the user to enter the file names?
Try using std::wstring and std::wcin along with std::getline

1
2
3
4
5
6
7
8
9
10
11
std::wstring inputFile, outputFile;

std::cout << "Input filename: ";
std::getline(std::wcin, intputFile);

std::cout << "Output filename: ";
std::getline(std::wcin, outputFile);

const WCHAR *input = inputFile.c_str();
const WCHAR *output = outputFile.c_str();
//... 


If you want to print them to the console use std::wcout.
1
2
std::wcout << "Input file\"" << input << std::endl;
std::wcout << "Output file\"" << output << std::endl;
You are great, Thanks a lot!
Topic archived. No new replies allowed.