将LPSTR和字符串添加到LPCTSTR中的斗争

时间:2015-11-20 19:51:57

标签: c++ string windows

我是C ++上的字符串的新手,我已经有几个小时了,我已经在很多论坛上了,所以我理解什么样的char *是LPSTR,LPCSTR或LPCSTR,但我找不到方式并了解如何使用它们构建字符串。

我打算使用GetCurrentDirectoryACopyFileA复制/粘贴新文件。

这是我的代码:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <winbase.h>


using namespace std;


#define DR drum-
#define NO normal-
#define SO soft-


//main
int main(){
LPCTSTR input;
LPCTSTR output;
LPSTR cd;
LPCSTR src = "source.wav";



if(GetCurrentDirectoryA(strlen(cd), cd)){
    input =  (LPCTSTR)cd + (LPCTSTR)src;


    if(CopyFileA(input, cd + "DR" + "hitclap.wav"))
        cout<<"done"<<endl;
    else
        cout<<"error"<<endl;
}
}

6 个答案:

答案 0 :(得分:2)

API private void ChangeToDoubleWhenLeave(object sender, EventArgs e) { var textBox = sender as TextBox; if (textBox != null) { double value; if (double.TryParse(textBox.Text, out value)) { textBox.Text = value.ToString("F"); } } } 不会向您返回新字符串。它的作用是将它传递给一个内存位置,并使用当前目录字符串填充该内存位置。

问题是你没有分配内存,你传递了未初始化的GetCurrentDirectorychar*),LPSTR。您还在此未初始化的字符指针上使用cd。通常,您使用长度为strlen的字符数组来播放文件名:

MAX_PATH

第二个注意事项是您不能使用char cd[MAX_PATH]; GetCurrentDirectoryA(sizeof(cd), cd); 运算符来连接C字符串。要么你去C路线并使用+ [1]和朋友,要么你去C ++路线并用strcat替换你所有的char*并使用它。

选择其中一条道路,然后阅读std::string上的教程 - C中的字符串或C ++中的char*

要正确理解std::string类型及其与LPTSTR的关系,请参阅我创建的this question & answer

[1] How do I concatenate const/literal strings in C?

答案 1 :(得分:1)

GetCurrentDirectory的签名是

DWORD WINAPI GetCurrentDirectory(
  _In_  DWORD  nBufferLength,
  _Out_ LPTSTR lpBuffer
);

lpBuffer是指向内存缓冲区的指针,其中应放置内容,nBufferLength是TCHAR中此内存区域的大小。

所以正确的代码是:

TCHAR szBuffer[MAX_PATH];
GetCurrentDirectory(MAX_PATH, szBuffer);

你必须使用TCHAR作为非unicode构建它将解析为char,而对于unicode它将是wchar_t。

答案 2 :(得分:1)

欢迎使用80286内存模型的遗留问题以及Windows操作系统使用的8位字符到(某种)unicode的演变。

LPCSTR表示:&#34;指向const字符串的长指针&#34;今天相当于const char*。不是很多年前它等同于const char* far - 远远是微软的扩展,告诉编译器地址可能在不同的内存段(如果你真的在乎,谷歌是你的朋友&#34;分段内存型号80286&#34;)

LPCTSTR表示:指向const的长指针[宽或8位,取决于编译器标志]字符。例如之一: const char*const wchar_t*取决于构建模式。

同样LPSTR今天char *,但曾经只有char * far

所以你可以看到Windows API实际上是使用原始指针到c样式的字符串,这些字符串是const或mutable,以及宽字符或8位字符,具体取决于上下文和构建选项。

答案 3 :(得分:1)

使用BoostFilesystem¹你会写:

<强> Live On Coliru

#include <boost/filesystem.hpp>
#include <iostream>

#define dr "drum -"
#define no "normal -"
#define so "soft -"

int main() {
    using boost::filesystem::path;

    auto input  = absolute(path("source.wav"));
    auto output = absolute(path(dr "hitclap.wav"));

    std::cout << input << " " << output << "\n";
}

打印

"/tmp/1448053072-1243850518/source.wav" "/tmp/1448053072-1243850518/drum -hitclap.wav"

你可以从那里拿走它。

  

¹注意:Microsoft Visual C ++发布了<filesystem>的版本,因为...... VS2010甚至我认为。所以你可能根本不需要提升来享受郁郁葱葱的生活:)

答案 4 :(得分:0)

每当我使用需要或使用LPSTR / LPCTSTR的东西时,我倾向于使用std :: wstring代替:

std::wstring input = _T("");
input.append(_T("Sample Text"));
input.append(std::to_wstring(myint));
std::copy(mystring.begin(), mystring.end(), text.end());

这使得可以使用字符串代替LPCTSTR。我不知道它是否适用于这种情况,但我认为它会。

编辑:正如@MicroVirus所说,你应该一路走下去并且使用TCHAR来做所有事情,这样你的程序就兼容ANSI和Unicode(你的函数使用ANSI,如尾随&#39; A& #39;)

答案 5 :(得分:0)

您可以使用以下命令将<string> STL库与Windows W API一起使用:

#include <cassert>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>

#include <windows.h>

using std::endl;
using std::cout;
using std::cerr;

using tstring = std::basic_string<TCHAR>;

const std::wstring dr = L"drum-";
// OR: const tstring dr = TEXT("drum-");
const std::wstring no = L"normal-";
const std::wstring so = L"soft-";
const std::wstring src = L"drum.wav";
const std::wstring dest = L"hitclap.wav";

int main()
{
   const std::vector<wchar_t>::size_type cd_buf_len = GetCurrentDirectoryW( 0, NULL );
   assert( cd_buf_len > 0 );
   std::vector<wchar_t> cwd( cd_buf_len, 0 );
   const DWORD cd_result = GetCurrentDirectoryW( cd_buf_len, cwd.data() );
   assert(cd_result);

   if (CopyFileW( (cwd.data() + src).c_str(), (cwd.data() + dr + dest).c_str(), FALSE )) {
       cout << "Done." << endl;
   } else {
       cerr << "Error." << endl;
       return EXIT_FAILURE;
   }

   return EXIT_SUCCESS;
}

此版本已修复以更正初始帖子中的错误:修改.c_str()会导致未定义的行为。它在概念上很简单并且按要求使用添加,但是不如分配缓冲区并将源字符串复制到它们或使用+=那样高效。因此,您可能真的想写:

constexpr wchar_t src[] = L"drum.wav";
/* … */
std::wstring src_path = cwd.data();
src_path += src;

要使用TCHAR版本,请将wchar_t更改为TCHAR,将L"foo"更改为TEXT("foo"),将std::wstring更改为tstring },将LPWSTR更改为LPTSTR,将GetCurrentDirectoryW更改为GetCurrentDirectory等。

通常,您不希望在同一程序中混合使用8位和宽字符串,除非您明确需要在一个编码中输入并在另一个编码中输出。如果是这样,您必须显式转换,例如将当前代码页设置为65001(UTF-8)并使用std::wstring_convert