首先请让我说我对客观的c开发很新。我正在为iphone编写一个供个人使用的小应用程序,但是在执行以下代码时遇到了一些问题:
NSString *sql = [[NSString alloc] initWithFormat:@"select color_r, color_g, color_b from Calendar where ROWID = %@", [calendarsID objectForKey:[arrayColors objectAtIndex:row]]];
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK)
编译器告诉我,我从不兼容的指针类型传递sqlite3_prepare_v2的参数2。无论如何,程序会被编译并运行,但是当它必须执行我刚刚向您显示的代码时,它会产生错误。它表示查询中存在语法错误,语法错误仅在查询的最后部分。而不是:
从日历中选择color_,color_g,color_b,其中ROWID = 63(例如)
我在最后一个数字(63)处得到奇怪的字符。我想这是一个与字符串转换有关的问题。可以请任何人帮助我吗?
非常感谢你的关注。 Alessio的
答案 0 :(得分:6)
问题是NSString
不是sqlite3_prepare_v2()
第二个参数所期望的。它需要一个const char*
。 C在这里有点松懈,它允许你隐式地将NSString*
强制转换为const char*
,这是错误的 - 编译器会给你一个你不应该忽略的警告。
您需要将NSString
转换为const char*
。最简单的方法是使用-UTF8String
消息将其转换为UTF-8:
// V---- HERE ----V
if(sqlite3_prepare_v2(database, [sql UTF8String], -1, &selectstmt, NULL) == SQLITE_OK)
或者,在您不希望使用其他编码的情况下,您可以使用-cStringUsingEncoding:
消息将字符串转换为使用特定字符编码的C字符串。
答案 1 :(得分:1)
我认为您的主要问题是您直接使用sqlite C api instead of a wrapper。
答案 2 :(得分:1)
为什么不使用SQLite的value binding API?该陈述看起来像
SELECT color_r, color_g, color_b FROM Calendar WHERE ROWID = ?;
您可以将参数直接传递给SQLite,以便安全地插入查询中。这将保护您免受SQL注入攻击。 (您显示的示例可能是安全的,具体取决于这些值最终来自哪里,但使用sprintf
或stringWithFormat:
来构建SQL查询是一个非常好的非常糟糕的习惯。不要被Little Bobby Tables 搞砸。)
至于你遇到问题的原因,SQLite不接受像NSString *这样的Cocoa类型。当您切换到使用SQLite格式化查询时,您将能够从其文档中学习您应该使用的类型。然后,您可以询问有关如何执行转换的其他问题。
答案 3 :(得分:0)
Alessio的,
用更多细节回答这个问题会更容易。例如,arrayColors中的对象类型是什么?
如果arrayColors中的对象不是NSStrings,那么你想调用一个方法(例如描述)来创建一个NSString表示。
亚伦