string.split
не поддерживается в LINQ-to-SQL.
Есть легкое исправление. Выберите все данные и выполните фильтрацию в клиенте. Это может быть не очень эффективным в зависимости от количества категорий.
var category =
_dataContext.Categories.ToList()
.Where<Category>(p => p.Keywords.Split(' ').Contains<string>(context.Request.QueryString["q"])).First();
Вызов .ToList()
заставит перечисление всех категорий из вашего источника данных, а последующие операции будут выполняться в клиентском коде.
Вы не можете сделать это напрямую, потому что у вас нет доступа на запись в базовый буфер (до C ++ 11; см. комментарий ). Вам нужно будет сначала сделать это в c-строке, а затем скопировать в std :: string:
char buff[100];
snprintf(buff, sizeof(buff), "%s", "Hello");
std::string buffAsStdStr = buff;
Но я не уверен, почему бы вам просто не использовать строковый поток? Я предполагаю, что у вас есть особые причины не делать это просто так:
std::ostringstream stringStream;
stringStream << "Hello";
std::string copyOfStr = stringStream.str();
Я попробовал, с регулярными выражениями . Я реализовал это для ints и const-строк в качестве примера, но вы можете добавить любые другие типы ( POD , но с помощью указателей вы можете печатать что угодно).
#include <assert.h>
#include <cstdarg>
#include <string>
#include <sstream>
#include <regex>
static std::string
formatArg(std::string argDescr, va_list args) {
std::stringstream ss;
if (argDescr == "i") {
int val = va_arg(args, int);
ss << val;
return ss.str();
}
if (argDescr == "s") {
const char *val = va_arg(args, const char*);
ss << val;
return ss.str();
}
assert(0); //Not implemented
}
std::string format(std::string fmt, ...) {
std::string result(fmt);
va_list args;
va_start(args, fmt);
std::regex e("\\{([^\\{\\}]+)\\}");
std::smatch m;
while (std::regex_search(fmt, m, e)) {
std::string formattedArg = formatArg(m[1].str(), args);
fmt.replace(m.position(), m.length(), formattedArg);
}
va_end(args);
return fmt;
}
Вот пример использования этого:
std::string formatted = format("I am {s} and I have {i} cats", "bob", 3);
std::cout << formatted << std::endl;
Вывод:
Я Боб, и у меня есть 3 кошки
Здесь мое (простое решение):
std::string Format(const char* lpszFormat, ...)
{
// Warning : "vsnprintf" crashes with an access violation
// exception if lpszFormat is not a "const char*" (for example, const string&)
size_t nSize = 1024;
char *lpBuffer = (char*)malloc(nSize);
va_list lpParams;
while (true)
{
va_start(lpParams, lpszFormat);
int nResult = vsnprintf(
lpBuffer,
nSize,
lpszFormat,
lpParams
);
va_end(lpParams);
if ((nResult >= 0) && (nResult < (int)nSize) )
{
// Success
lpBuffer[nResult] = '\0';
std::string sResult(lpBuffer);
free (lpBuffer);
return sResult;
}
else
{
// Increase buffer
nSize =
(nResult < 0)
? nSize *= 2
: (nResult + 1)
;
lpBuffer = (char *)realloc(lpBuffer, nSize);
}
}
}
Похоже, что все ответы здесь до сих пор имеют одну или несколько из следующих проблем: (1) он может не работать на VC ++ (2) он требует дополнительных зависимостей, таких как boost или fmt (3), его слишком сложная пользовательская реализация и, вероятно, нет хорошо проверено.
Ниже приведен код для решения всех вышеперечисленных проблем.
#include <string>
#include <cstdarg>
#include <memory>
std::string stringf(const char* format, ...)
{
va_list args;
va_start(args, format);
#ifndef _MSC_VER
//GCC generates warning for valid use of snprintf to get
//size of result string. We suppress warning with below macro.
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
size_t size = std::snprintf(nullptr, 0, format, args) + 1; // Extra space for '\0'
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
std::unique_ptr<char[]> buf(new char[ size ] );
std::vsnprintf(buf.get(), size, format, args);
return std::string(buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
#else
int size = _vscprintf(format, args);
std::string result(++size, 0);
vsnprintf_s((char*)result.data(), size, _TRUNCATE, format, args);
return result;
#endif
va_end(args);
}
int main() {
float f = 3.f;
int i = 5;
std::string s = "hello!";
auto rs = stringf("i=%d, f=%f, s=%s", i, f, s.c_str());
printf("%s", rs.c_str());
return 0;
}
Примечания:
snprintf
, который будет генерировать предупреждения компилятора для других ответов с высоким рейтингом выше. Поскольку я всегда работаю в режиме «предупреждения как ошибки», мне это не подходит. char *
вместо std::string
. Это потому, что большую часть времени эта функция вызывается с литеральной строкой, которая действительно char *
, а не std::string
. Если у вас есть std::string
в качестве параметра формата, просто позвоните .c_str()
. #pragma
макросов для подавления ложных срабатываний в предупреждениях GCC. Выше код был протестирован,
C++ 20 std::format
Это прибыло! Функция описана в: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0645r9.html и использование подобное Python .format()
синтаксис.
я ожидаю, что использование будет похоже:
#include <format>
#include <string>
int main() {
std::string message = std::format("The answer is {}.", 42);
}
я дам ему попытку, когда поддержка прибудет в GCC, GCC 9.1.0 с g++-9 -std=c++2a
все еще не поддерживает его.
API добавит новое std::format
заголовок:
предложенное форматирование API определяется в новом заголовке
<format>
и не должен оказывать влияние на существующий код.
существующее fmt
библиотека утверждает, что реализовала его при необходимости в полизаливке: https://реализация github.com/fmtlib/fmt
C++ 20
std::format
.
и был ранее упомянут в: станд.:: строка, форматирующая как sprintf
Если вам нужен синтаксис, подобный printf (без вызова printf самостоятельно), посмотрите Boost Format .
boost :: format ()
обеспечивает желаемую функциональность:
Согласно синопсису библиотек формата Boost:
Объект формата создается из строки формата, а затем ему передаются аргументы через повторение вызовы оператора%. Каждый из этих аргументов затем преобразуется в строки, которые, в свою очередь, объединяются в одну строку в соответствии со строкой формата.
#include <boost/format.hpp>
cout << boost::format("writing %1%, x=%2% : %3%-th try") % "toto" % 40.23 % 50;
// prints "writing toto, x=40.230 : 50-th try"
строка не имеет того, что вам нужно, но std :: stringstream есть. Используйте поток строк для создания строки, а затем извлеките строку. Здесь - полный список того, что вы можете делать. Например:
cout.setprecision(10); //stringstream is a stream like cout
даст вам 10 десятичных знаков точности при печати двойного или плавающего числа.